diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index e3ca197c..7f87653e 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -53,14 +53,14 @@ if (${EMSCRIPTEN}) target_compile_options (${TARGET} PUBLIC $<$:-O3> $<$:-flto> - -sDISABLE_EXCEPTION_CATCHING=1 + $,-sDISABLE_EXCEPTION_CATCHING=1,-sDISABLE_EXCEPTION_CATCHING=0> -DOCCT_NO_PLUGINS ) target_link_options (${TARGET} PUBLIC - $<$:-O3> + $,-O3,-O0> $<$:-flto> - -sDISABLE_EXCEPTION_CATCHING=1 + $,-sDISABLE_EXCEPTION_CATCHING=1,-sDISABLE_EXCEPTION_CATCHING=0> -sMODULARIZE=1 -sEXPORT_ES6=1 -sALLOW_MEMORY_GROWTH=1 diff --git a/cpp/src/converter.cpp b/cpp/src/converter.cpp new file mode 100644 index 00000000..8e2155a3 --- /dev/null +++ b/cpp/src/converter.cpp @@ -0,0 +1,33 @@ +#include +#include +#include +#include +#include + +using namespace emscripten; + +class Converter { +public: + 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) { + std::istringstream iss(input); + TopoDS_Shape output; + BRep_Builder builder; + BRepTools::Read(output, iss, builder); + return output; + } + +}; + +EMSCRIPTEN_BINDINGS(Converter) +{ + class_("Converter") + .class_function("convertToBrep", &Converter::convertToBrep) + .class_function("convertFromBrep", &Converter::convertFromBrep) + ; +} \ No newline at end of file diff --git a/cpp/src/factory.cpp b/cpp/src/factory.cpp new file mode 100644 index 00000000..16ce91ac --- /dev/null +++ b/cpp/src/factory.cpp @@ -0,0 +1,360 @@ +#include "shared.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace emscripten; + +struct ShapeResult +{ + TopoDS_Shape shape; + bool isOk; + std::string error; +}; + +class ShapeFactory +{ +public: + static ShapeResult box(const Ax3 &ax3, double x, double y, double z) + { + gp_Pln pln = Ax3::toPln(ax3); + BRepBuilderAPI_MakeFace makeFace(pln, 0, x, 0, y); + if (!makeFace.IsDone()) + { + return ShapeResult{TopoDS_Shape(), false, "Failed to create box"}; + } + + gp_Vec vec(pln.Axis().Direction()); + vec.Multiply(z); + BRepPrimAPI_MakePrism box(makeFace.Face(), vec); + if (!box.IsDone()) + { + return ShapeResult{TopoDS_Shape(), false, "Failed to create box"}; + } + return ShapeResult{box.Shape(), true, ""}; + } + + static ShapeResult sweep(const TopoDS_Shape &profile, const TopoDS_Wire &wire) + { + BRepOffsetAPI_MakePipe pipe(wire, profile); + if (!pipe.IsDone()) + { + return ShapeResult{TopoDS_Shape(), false, "Failed to sweep profile"}; + } + return ShapeResult{pipe.Shape(), true, ""}; + } + + static ShapeResult revolve(const TopoDS_Shape &profile, const Ax1 &axis, double rad) + { + BRepPrimAPI_MakeRevol revol(profile, Ax1::toAx1(axis), rad); + if (!revol.IsDone()) + { + return ShapeResult{TopoDS_Shape(), false, "Failed to revolve profile"}; + } + return ShapeResult{revol.Shape(), true, ""}; + } + + static ShapeResult prism(const TopoDS_Shape &profile, const Vector3 &vec) + { + gp_Vec vec3 = Vector3::toVec(vec); + BRepPrimAPI_MakePrism prism(profile, vec3); + if (!prism.IsDone()) + { + return ShapeResult{TopoDS_Shape(), false, "Failed to create prism"}; + } + return ShapeResult{prism.Shape(), true, ""}; + } + + static ShapeResult polygon(const Vector3Array &points) + { + std::vector pts = vecFromJSArray(points); + BRepBuilderAPI_MakePolygon poly; + for (auto &p : pts) + { + poly.Add(Vector3::toPnt(p)); + } + if (!poly.IsDone()) + { + return ShapeResult{TopoDS_Shape(), false, "Failed to create polygon"}; + } + return ShapeResult{poly.Wire(), true, ""}; + } + + static ShapeResult arc(const Vector3 &normal, const Vector3 ¢er, const Vector3 &start, double rad) + { + gp_Pnt centerPnt = Vector3::toPnt(center); + gp_Pnt startPnt = Vector3::toPnt(start); + gp_Dir xvec = gp_Dir(startPnt.XYZ() - centerPnt.XYZ()); + gp_Ax2 ax2(centerPnt, Vector3::toDir(normal), xvec); + gp_Circ circ(ax2, centerPnt.Distance(startPnt)); + double startAng(0), endAng(rad); + if (rad < 0) { + startAng = Math::PI_2 + rad; + endAng = Math::PI_2; + } + BRepBuilderAPI_MakeEdge edge(circ, startAng, endAng); + if (!edge.IsDone()) + { + return ShapeResult{TopoDS_Shape(), false, "Failed to create arc"}; + } + return ShapeResult{edge.Edge(), true, ""}; + } + + static ShapeResult circle(const Vector3 &normal, const Vector3 ¢er, double radius) + { + gp_Ax2 ax2(Vector3::toPnt(center), Vector3::toDir(normal)); + gp_Circ circ(ax2, radius); + BRepBuilderAPI_MakeEdge edge(circ); + if (!edge.IsDone()) + { + return ShapeResult{TopoDS_Shape(), false, "Failed to create circle"}; + } + return ShapeResult{edge.Edge(), true, ""}; + } + + static ShapeResult rect(const Ax3 &pln, double width, double height) + { + BRepBuilderAPI_MakeFace makeFace(Ax3::toPln(pln), 0, width, 0, height); + if (!makeFace.IsDone()) + { + return ShapeResult{TopoDS_Shape(), false, "Failed to create rectangle"}; + } + return ShapeResult{makeFace.Face(), true, ""}; + } + + static ShapeResult bezier(const Vector3Array &points, const NumberArray &weights) + { + std::vector pts = vecFromJSArray(points); + TColgp_Array1OfPnt arrayofPnt(1, pts.size()); + for (int i = 0; i < pts.size(); i++) + { + arrayofPnt.SetValue(i + 1, Vector3::toPnt(pts[i])); + } + + std::vector wts = vecFromJSArray(weights); + TColStd_Array1OfReal arrayOfWeight(1, wts.size()); + for (int i = 0; i < wts.size(); i++) + { + arrayOfWeight.SetValue(i + 1, wts[i]); + } + + Handle_Geom_Curve curve = wts.size() > 0 + ? new Geom_BezierCurve(arrayofPnt, arrayOfWeight) + : new Geom_BezierCurve(arrayofPnt); + BRepBuilderAPI_MakeEdge edge(curve); + if (!edge.IsDone()) + { + return ShapeResult{TopoDS_Shape(), false, "Failed to create bezier"}; + } + return ShapeResult{edge.Edge(), true, ""}; + } + + static ShapeResult point(const Vector3 &point) + { + BRepBuilderAPI_MakeVertex makeVertex(Vector3::toPnt(point)); + if (!makeVertex.IsDone()) + { + return ShapeResult{TopoDS_Shape(), false, "Failed to create point"}; + } + return ShapeResult{makeVertex.Vertex(), true, ""}; + } + + static ShapeResult line(const Vector3 &start, const Vector3 &end) + { + BRepBuilderAPI_MakeEdge makeEdge(Vector3::toPnt(start), Vector3::toPnt(end)); + if (!makeEdge.IsDone()) + { + return ShapeResult{TopoDS_Shape(), false, "Failed to create line"}; + } + return ShapeResult{makeEdge.Edge(), true, ""}; + } + + static void orderEdge(BRepBuilderAPI_MakeWire& wire, const std::vector &edges) + { + ShapeAnalysis_WireOrder order; + ShapeAnalysis_Edge analysis; + for (auto &edge : edges) + { + order.Add( + BRep_Tool::Pnt(analysis.FirstVertex(edge)).XYZ(), + BRep_Tool::Pnt(analysis.LastVertex(edge)).XYZ()); + } + order.Perform(true); + if (order.IsDone()) + { + for (int i = 0; i < order.NbEdges(); i++) + { + int index = order.Ordered(i + 1); + auto edge = edges[abs(index) - 1]; + if (index < 0) + { + edge.Reverse(); + } + wire.Add(edge); + } + } + + } + + static ShapeResult wire(const EdgeArray &edges) + { + std::vector edgesVec = vecFromJSArray(edges); + if (edgesVec.size() == 0) + { + return ShapeResult{TopoDS_Shape(), false, "No edges provided"}; + } + BRepBuilderAPI_MakeWire wire; + if (edgesVec.size() == 1) + { + wire.Add(edgesVec[0]); + } + else + { + orderEdge(wire, edgesVec); + } + + if (!wire.IsDone()) + { + return ShapeResult{TopoDS_Shape(), false, "Failed to create wire"}; + } + return ShapeResult{wire.Wire(), true, ""}; + } + + static ShapeResult face(const WireArray& wires) { + std::vector wiresVec = vecFromJSArray(wires); + BRepBuilderAPI_MakeFace makeFace(wiresVec[0]); + for (int i = 1; i < wiresVec.size(); i++) { + makeFace.Add(wiresVec[i]); + } + if (!makeFace.IsDone()) { + return ShapeResult{TopoDS_Shape(), false, "Failed to create face"}; + } + return ShapeResult{makeFace.Face(), true, ""}; + } + + static ShapeResult makeThickSolidBySimple(const TopoDS_Shape &shape, double thickness) { + BRepOffsetAPI_MakeThickSolid makeThickSolid; + makeThickSolid.MakeThickSolidBySimple(shape, thickness); + if (!makeThickSolid.IsDone()) { + return ShapeResult{TopoDS_Shape(), false, "Failed to create thick solid"}; + } + return ShapeResult{makeThickSolid.Shape(), true, ""}; + } + + static ShapeResult makeThickSolidByJoin(const TopoDS_Shape &shape, const ShapeArray &shapes, double thickness) { + std::vector shapesVec = vecFromJSArray(shapes); + TopTools_ListOfShape shapesList; + for (auto shape : shapesVec) { + shapesList.Append(shape); + } + BRepOffsetAPI_MakeThickSolid makeThickSolid; + makeThickSolid.MakeThickSolidByJoin(shape, shapesList, thickness, 1e-6); + if (!makeThickSolid.IsDone()) { + return ShapeResult{TopoDS_Shape(), false, "Failed to create thick solid"}; + } + return ShapeResult{makeThickSolid.Shape(), true, ""}; + } + + static ShapeResult booleanOperate(BRepAlgoAPI_BooleanOperation& boolOperater, const ShapeArray &args, const ShapeArray& tools) { + std::vector argsVec = vecFromJSArray(args); + TopTools_ListOfShape argsList; + for (auto shape : argsVec) { + argsList.Append(shape); + } + + std::vector toolsVec = vecFromJSArray(tools); + TopTools_ListOfShape toolsList; + for (auto shape : toolsVec) { + toolsList.Append(shape); + } + + boolOperater.SetArguments(argsList); + boolOperater.SetTools(toolsList); + boolOperater.Build(); + if (!boolOperater.IsDone()) { + return ShapeResult{TopoDS_Shape(), false, "Failed to build boolean operation"}; + } + return ShapeResult{boolOperater.Shape(), true, ""}; + } + + static ShapeResult booleanCommon(const ShapeArray &args, const ShapeArray& tools) { + BRepAlgoAPI_Common api; + api.SetRunParallel(true); + return booleanOperate(api, args, tools); + } + + static ShapeResult booleanCut(const ShapeArray &args, const ShapeArray& tools) { + BRepAlgoAPI_Cut api; + api.SetRunParallel(true); + return booleanOperate(api, args, tools); + } + + static ShapeResult booleanFuse(const ShapeArray &args, const ShapeArray& tools) { + BRepAlgoAPI_Fuse api; + api.SetRunParallel(true); + return booleanOperate(api, args, tools); + } + + static ShapeResult combine(const ShapeArray &shapes) { + std::vector shapesVec = vecFromJSArray(shapes); + TopoDS_Compound compound; + BRep_Builder builder; + builder.MakeCompound(compound); + for (auto shape : shapesVec) { + builder.Add(compound, shape); + } + return ShapeResult{compound, true, ""}; + } + +}; + +EMSCRIPTEN_BINDINGS(ShapeFactory) +{ + class_("ShapeResult") + .property("shape", &ShapeResult::shape) + .property("isOk", &ShapeResult::isOk) + .property("error", &ShapeResult::error); + + class_("ShapeFactory") + .class_function("box", &ShapeFactory::box) + .class_function("sweep", &ShapeFactory::sweep) + .class_function("revolve", &ShapeFactory::revolve) + .class_function("prism", &ShapeFactory::prism) + .class_function("polygon", &ShapeFactory::polygon) + .class_function("circle", &ShapeFactory::circle) + .class_function("arc", &ShapeFactory::arc) + .class_function("bezier", &ShapeFactory::bezier) + .class_function("rect", &ShapeFactory::rect) + .class_function("point", &ShapeFactory::point) + .class_function("line", &ShapeFactory::line) + .class_function("wire", &ShapeFactory::wire) + .class_function("face", &ShapeFactory::face) + .class_function("makeThickSolidBySimple", &ShapeFactory::makeThickSolidBySimple) + .class_function("makeThickSolidByJoin", &ShapeFactory::makeThickSolidByJoin) + .class_function("booleanCommon", &ShapeFactory::booleanCommon) + .class_function("booleanCut", &ShapeFactory::booleanCut) + .class_function("booleanFuse", &ShapeFactory::booleanFuse) + .class_function("combine", &ShapeFactory::combine) + + ; + +} \ No newline at end of file diff --git a/cpp/src/geometry.cpp b/cpp/src/geometry.cpp index 3fde3111..7a3ee1f6 100644 --- a/cpp/src/geometry.cpp +++ b/cpp/src/geometry.cpp @@ -1,13 +1,260 @@ +#include "shared.hpp" #include +#include +#include +#include +#include +#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include -class Geometry { -public: +using namespace emscripten; + +struct ProjectPointResult { + Vector3 point; + double distance; + double parameter; +}; +struct ExtremaCCResult { + bool isParallel; + double distance; + Vector3 p1; + Vector3 p2; + double u1; + double u2; }; + class Curve { +private: + static Vector3Array getPoints(const GCPnts_UniformAbscissa& uniformAbscissa, const Geom_Curve* curve) { + std::vector points; + for (int i = 1; i <= uniformAbscissa.NbPoints(); i++) { + points.push_back(Vector3::fromPnt(curve->Value(uniformAbscissa.Parameter(i)))); + } + return Vector3Array(val::array(points)); + } + +public: + static Handle_Geom_Line makeLine(const Vector3& start, const Vector3& dir) { + Handle_Geom_Line line = new Geom_Line(Vector3::toPnt(start), Vector3::toDir(dir)); + return line; + } + + static Handle_Geom_TrimmedCurve trim(const Geom_Curve* curve, double start, double end) { + Handle_Geom_TrimmedCurve trimmedCurve = new Geom_TrimmedCurve(curve, start, end); + return trimmedCurve; + } + + static Vector3Array projects(const Geom_Curve* curve, const Vector3& point) { + GeomAPI_ProjectPointOnCurve projector(Vector3::toPnt(point), curve); + std::vector points; + for (int i = 1; i <= projector.NbPoints(); i++) { + points.push_back(Vector3::fromPnt(projector.Point(i))); + } + + return Vector3Array(val::array(points)); + } + + static std::optional nearestExtremaCC(const Geom_Curve* curve1, const Geom_Curve* curve2) { + GeomAPI_ExtremaCurveCurve extrema(curve1, curve2); + if (extrema.NbExtrema() == 0) { + return std::nullopt; + } + + gp_Pnt p1, p2; + extrema.NearestPoints(p1, p2); + double u1, u2; + extrema.LowerDistanceParameters(u1, u2); + return ExtremaCCResult { + .isParallel = extrema.IsParallel(), + .distance = extrema.LowerDistance(), + .p1 = Vector3::fromPnt(p1), + .p2 = Vector3::fromPnt(p2), + .u1 = u1, + .u2 = u2 + }; + } + + static Vector3Array uniformAbscissaWithLength(const Geom_Curve* curve, double length) { + GeomAdaptor_Curve adaptorCurve(curve); + GCPnts_UniformAbscissa uniformAbscissa(adaptorCurve, length); + return getPoints(uniformAbscissa, curve); + } + + static Vector3Array uniformAbscissaWithCount(const Geom_Curve* curve, int nbPoints) { + GeomAdaptor_Curve adaptorCurve(curve); + GCPnts_UniformAbscissa uniformAbscissa(adaptorCurve, nbPoints); + return getPoints(uniformAbscissa, curve); + } + + static ProjectPointResult projectOrNearest(const Geom_Curve* curve, const Vector3& point) { + gp_Pnt pnt = Vector3::toPnt(point); + GeomAPI_ProjectPointOnCurve projector(pnt, curve); + if (projector.NbPoints() > 0) { + return ProjectPointResult { + .point = Vector3::fromPnt(projector.NearestPoint()), + .distance = projector.LowerDistance(), + .parameter = projector.LowerDistanceParameter() + }; + } + + gp_Pnt start = curve->Value(curve->FirstParameter()); + gp_Pnt end = curve->Value(curve->LastParameter()); + double distanceToStart = pnt.Distance(start); + double distanceToEnd = pnt.Distance(end); + if (distanceToStart < distanceToEnd) { + return ProjectPointResult { + .point = Vector3::fromPnt(start), + .distance = distanceToStart, + .parameter = curve->FirstParameter() + }; + } else { + return ProjectPointResult { + .point = Vector3::fromPnt(end), + .distance = distanceToEnd, + .parameter = curve->LastParameter() + }; + } + } + + static std::optional parameter(const Geom_Curve* curve, const Vector3& point, double maxDistance) { + double parameter = 0; + gp_Pnt pnt = Vector3::toPnt(point); + if (GeomLib_Tool::Parameter(curve, pnt, maxDistance, parameter)) { + return parameter; + } + return std::nullopt; + } + + static double curveLength(const Geom_Curve* curve) { + GeomAdaptor_Curve adaptorCurve(curve); + return GCPnts_AbscissaPoint::Length(adaptorCurve); + } + +}; + +struct SurfaceBounds { + double u1; + double u2; + double v1; + double v2; +}; + +class Surface { public: + static Handle_Geom_Curve projectCurve(const Geom_Surface* surface, const Geom_Curve* curve) { + return GeomProjLib::Project(curve, surface); + } + + static Vector3Array projectPoint(const Geom_Surface* surface, const Vector3& point) { + gp_Pnt pnt = Vector3::toPnt(point); + GeomAPI_ProjectPointOnSurf projector(pnt, surface); + std::vector points; + for (size_t i = 0; i < projector.NbPoints(); i++) + { + points.push_back(projector.Point(i + 1)); + } + + return Vector3Array(val::array(points.begin(), points.end())); + } + + static bool isPlanar(const Geom_Surface* surface) { + GeomLib_IsPlanarSurface isPlanarSurface(surface); + return isPlanarSurface.IsPlanar(); + } + + static std::optional parameters(const Geom_Surface* surface, const Vector3& point, double maxDistance) { + double u(0), v(0); + gp_Pnt pnt = Vector3::toPnt(point); + if (GeomLib_Tool::Parameters(surface, pnt, maxDistance, u, v)) { + return UV { + .u = u, + .v = v + }; + } + return std::nullopt; + } + + static std::optional nearestPoint(const Geom_Surface* surface, const Vector3& point) { + gp_Pnt pnt = Vector3::toPnt(point); + GeomAPI_ProjectPointOnSurf projector(pnt, surface); + if (projector.IsDone()) { + return PointAndParameter { + .point = Vector3::fromPnt(projector.NearestPoint()), + .parameter = projector.LowerDistance() + }; + } + return std::nullopt; + } + + static SurfaceBounds bounds(const Geom_Surface* surface) { + double u1, u2, v1, v2; + surface->Bounds(u1, u2, v1, v2); + return SurfaceBounds { + .u1 = u1, + .u2 = u2, + .v1 = v1, + .v2 = v2 + }; + } + +}; + +EMSCRIPTEN_BINDINGS(Geometry) { + register_optional(); + + value_object("ProjectPointResult") + .field("point", &ProjectPointResult::point) + .field("distance", &ProjectPointResult::distance) + .field("parameter", &ProjectPointResult::parameter) + ; + + value_object("ExtremaCCResult") + .field("distance", &ExtremaCCResult::distance) + .field("p1", &ExtremaCCResult::p1) + .field("p2", &ExtremaCCResult::p2) + .field("isParallel", &ExtremaCCResult::isParallel) + .field("u1", &ExtremaCCResult::u1) + .field("u2", &ExtremaCCResult::u2) + ; + + class_("Curve") + .class_function("makeLine", &Curve::makeLine) + .class_function("trim", &Curve::trim, allow_raw_pointers()) + .class_function("projectOrNearest", &Curve::projectOrNearest, allow_raw_pointers()) + .class_function("uniformAbscissaWithCount", &Curve::uniformAbscissaWithCount, allow_raw_pointers()) + .class_function("uniformAbscissaWithLength", &Curve::uniformAbscissaWithLength, allow_raw_pointers()) + .class_function("nearestExtremaCC", &Curve::nearestExtremaCC, allow_raw_pointers()) + .class_function("parameter", &Curve::parameter, allow_raw_pointers()) + .class_function("curveLength", &Curve::curveLength, allow_raw_pointers()) + .class_function("projects", &Curve::projects, allow_raw_pointers()) + ; + + value_object("SurfaceBounds") + .field("u1", &SurfaceBounds::u1) + .field("u2", &SurfaceBounds::u2) + .field("v1", &SurfaceBounds::v1) + .field("v2", &SurfaceBounds::v2) + ; + + class_("Surface") + .class_function("projectCurve", &Surface::projectCurve, allow_raw_pointers()) + .class_function("projectPoint", &Surface::projectPoint, allow_raw_pointers()) + .class_function("isPlanar", &Surface::isPlanar, allow_raw_pointers()) + .class_function("parameters", &Surface::parameters, allow_raw_pointers()) + .class_function("nearestPoint", &Surface::nearestPoint, allow_raw_pointers()) + .class_function("bounds", &Surface::bounds, allow_raw_pointers()) + ; -}; \ No newline at end of file +} \ No newline at end of file diff --git a/cpp/src/mesher.cpp b/cpp/src/mesher.cpp index fb30bf39..760abe55 100644 --- a/cpp/src/mesher.cpp +++ b/cpp/src/mesher.cpp @@ -43,28 +43,37 @@ class EdgeMesher TopExp::MapShapes(this->shape, TopAbs_EDGE, edgeMap); for (TopTools_IndexedMapOfShape::Iterator anIt(edgeMap); anIt.More(); anIt.Next()) { - auto start = this->position.size() / 3; - TopoDS_Edge edge = TopoDS::Edge(anIt.Value()); edges.push_back(edge); generateEdgeMesh(edge, transform); - - this->group.push_back(start); - this->group.push_back(this->position.size() / 3 - start); } } void generateEdgeMesh(const TopoDS_Edge& edge, const gp_Trsf &transform) { + auto start = this->position.size() / 3; + BRepAdaptor_Curve curve(edge); GCPnts_TangentialDeflection pnts(curve, ANGLE_DEFLECTION, this->lineDeflection); + std::optional prePnt = std::nullopt; for (int i = 0; i < pnts.NbPoints(); i++) { auto pnt = pnts.Value(i + 1).Transformed(transform); - position.push_back(pnt.X()); - position.push_back(pnt.Y()); - position.push_back(pnt.Z()); + if (prePnt.has_value()) { + auto pre = prePnt.value(); + this->position.push_back(pre.X()); + this->position.push_back(pre.Y()); + this->position.push_back(pre.Z()); + + this->position.push_back(pnt.X()); + this->position.push_back(pnt.Y()); + this->position.push_back(pnt.Z()); + } + prePnt = pnt; } + + this->group.push_back(start); + this->group.push_back(this->position.size() / 3 - start); } public: @@ -73,14 +82,14 @@ class EdgeMesher generateEdgeMeshs(); } - Float32Array getPosition() + NumberArray getPosition() { - return Float32Array(val(typed_memory_view(position.size(), position.data()))); + return NumberArray(val::array(position)); } - Uint32Array getGroups() + NumberArray getGroups() { - return Uint32Array(val(typed_memory_view(group.size(), group.data()))); + return NumberArray(val::array(group)); } size_t getEdgeSize() @@ -94,7 +103,7 @@ class EdgeMesher } EdgeArray getEdges() { - return EdgeArray(val::array(edges.begin(), edges.end())); + return EdgeArray(val::array(edges)); } }; @@ -113,22 +122,18 @@ class FaceMesher void generateFaceMeshs() { - auto transform = shape.Location().Transformation().Inverted(); + auto totleTransform = shape.Location().Transformation().Inverted(); TopTools_IndexedMapOfShape faceMap; TopExp::MapShapes(this->shape, TopAbs_FACE, faceMap); for (TopTools_IndexedMapOfShape::Iterator anIt(faceMap); anIt.More(); anIt.Next()) { - auto start = this->position.size() / 3; auto face = TopoDS::Face(anIt.Value()); faces.push_back(face); - generateFaceMesh(face, transform); - - this->group.push_back(start); - this->group.push_back(this->position.size() / 3 - start); + generateFaceMesh(face, totleTransform); } } - void generateFaceMesh(const TopoDS_Face &face, const gp_Trsf &transform) + void generateFaceMesh(const TopoDS_Face &face, const gp_Trsf &totleTransform) { TopLoc_Location location; auto handlePoly = BRep_Tool::Triangulation(face, location); @@ -138,15 +143,19 @@ class FaceMesher } auto trsf = location.Transformation(); + trsf = trsf.Multiplied(totleTransform); bool isMirrod = trsf.VectorialPart().Determinant() < 0; - trsf = trsf.Multiplied(transform); auto orientation = face.Orientation(); - auto startIndex = this->position.size() / 3; + auto groupStart = this->index.size(); + auto indexStart = this->position.size() / 3; - this->fillIndex(startIndex, handlePoly, orientation); - this->fillPosition(transform, handlePoly); - this->fillNormal(transform, face, handlePoly, (orientation == TopAbs_REVERSED) ^ isMirrod); + this->fillIndex(indexStart, handlePoly, orientation); + this->fillPosition(trsf, handlePoly); + this->fillNormal(trsf, face, handlePoly, (orientation == TopAbs_REVERSED) ^ isMirrod); this->fillUv(face, handlePoly); + + this->group.push_back(groupStart); + this->group.push_back(this->index.size() - groupStart); } void fillPosition(const gp_Trsf &transform, const Handle(Poly_Triangulation) & handlePoly) @@ -176,7 +185,7 @@ class FaceMesher } } - void fillIndex(size_t startIndex, const Handle(Poly_Triangulation) & handlePoly, const TopAbs_Orientation &orientation) + void fillIndex(size_t indexStart, const Handle(Poly_Triangulation) & handlePoly, const TopAbs_Orientation &orientation) { for (int index = 0; index < handlePoly->NbTriangles(); index++) { @@ -188,15 +197,15 @@ class FaceMesher } auto triangle = handlePoly->Triangle(index + 1); - this->index.push_back(triangle.Value(v1) - 1 + startIndex); - this->index.push_back(triangle.Value(v2) - 1 + startIndex); - this->index.push_back(triangle.Value(v3) - 1 + startIndex); + this->index.push_back(triangle.Value(v1) - 1 + indexStart); + this->index.push_back(triangle.Value(v2) - 1 + indexStart); + this->index.push_back(triangle.Value(v3) - 1 + indexStart); } } void fillUv(const TopoDS_Face &face, const Handle(Poly_Triangulation) & handlePoly) { - double aUmin (0.0), aUmax (0.0), aVmin (0.0), aVmax (0.0), dUmax (0.0), dVmax (0.0); + double aUmin, aUmax, aVmin, aVmax, dUmax, dVmax; BRepTools::UVBounds (face, aUmin, aUmax, aVmin, aVmax); dUmax = (aUmax - aUmin); dVmax = (aVmax - aVmin); @@ -215,29 +224,29 @@ class FaceMesher generateFaceMeshs(); } - Float32Array getPosition() + NumberArray getPosition() { - return Float32Array(val(typed_memory_view(position.size(), position.data()))); + return NumberArray(val::array(position)); } - Float32Array getNormal() + NumberArray getNormal() { - return Float32Array(val(typed_memory_view(normal.size(), normal.data()))); + return NumberArray(val::array(normal)); } - Float32Array getUV() + NumberArray getUV() { - return Float32Array(val(typed_memory_view(uv.size(), uv.data()))); + return NumberArray(val::array(uv)); } - Uint32Array getIndex() + NumberArray getIndex() { - return Uint32Array(val(typed_memory_view(index.size(), index.data()))); + return NumberArray(val::array(index)); } - Uint32Array getGroups() + NumberArray getGroups() { - return Uint32Array(val(typed_memory_view(group.size(), group.data()))); + return NumberArray(val::array(group)); } size_t getFaceSize() @@ -250,7 +259,7 @@ class FaceMesher } FaceArray getFaces() { - return FaceArray(val::array(faces.begin(), faces.end())); + return FaceArray(val::array(faces)); } }; diff --git a/cpp/src/opencascade.cpp b/cpp/src/opencascade.cpp index a46ca3e5..b1e295f2 100644 --- a/cpp/src/opencascade.cpp +++ b/cpp/src/opencascade.cpp @@ -1,13 +1,40 @@ +#include "shared.hpp" #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include +#include +#include #include #include #include #include #include #include +#include #include #include #include @@ -17,11 +44,22 @@ #include #include #include +#include using namespace emscripten; EMSCRIPTEN_BINDINGS(opencascade) { + enum_("GeomAbs_Shape") + .value("GeomAbs_C0", GeomAbs_C0) + .value("GeomAbs_C1", GeomAbs_C1) + .value("GeomAbs_C2", GeomAbs_C2) + .value("GeomAbs_C3", GeomAbs_C3) + .value("GeomAbs_CN", GeomAbs_CN) + .value("GeomAbs_G1", GeomAbs_G1) + .value("GeomAbs_G2", GeomAbs_G2) + ; + enum_("GeomAbs_JoinType") .value("GeomAbs_Arc", GeomAbs_Arc) .value("GeomAbs_Intersection", GeomAbs_Intersection) @@ -40,7 +78,6 @@ EMSCRIPTEN_BINDINGS(opencascade) { .value("TopAbs_SHAPE", TopAbs_SHAPE) ; - enum_("TopAbs_Orientation") .value("TopAbs_FORWARD", TopAbs_FORWARD) .value("TopAbs_REVERSED", TopAbs_REVERSED) @@ -48,34 +85,239 @@ EMSCRIPTEN_BINDINGS(opencascade) { .value("TopAbs_EXTERNAL", TopAbs_EXTERNAL) ; - class_("Standard_Transient"); - class_>("Geom_Geometry"); + class_("Standard_Transient") + .function("getRefCount", &Standard_Transient::GetRefCount) + ; + + class_>("Geom_Geometry") + .function("copy", &Geom_Geometry::Copy) + ; + class_>("Geom_Curve") .function("isClosed", &Geom_Curve::IsClosed) .function("isPeriodic", &Geom_Curve::IsPeriodic) .function("period", &Geom_Curve::Period) .function("reverse", &Geom_Curve::Reverse) + .function("reversed", &Geom_Curve::Reversed) + .function("d0", &Geom_Curve::D0) .function("d1", &Geom_Curve::D1) .function("d2", &Geom_Curve::D2) .function("d3", &Geom_Curve::D3) - .function("d4", &Geom_Curve::DN) + .function("dn", &Geom_Curve::DN) + .function("isCN", &Geom_Curve::IsCN) .function("firstParameter", &Geom_Curve::FirstParameter) .function("lastParameter", &Geom_Curve::LastParameter) .function("value", &Geom_Curve::Value) + .function("continutity", &Geom_Curve::Continuity) + ; + + class_>("Geom_Conic") + .function("axis", &Geom_Conic::Axis) + .function("xAxis", &Geom_Conic::XAxis) + .function("yAxis", &Geom_Conic::YAxis) + .function("eccentricity", &Geom_Conic::Eccentricity) + ; + + class_>("Geom_Circle") + .function("radius", &Geom_Circle::Radius) + .function("setRadius", &Geom_Circle::SetRadius) + .function("location", &Geom_Circle::Location) + .function("setLocation", &Geom_Circle::SetLocation) + ; + + class_>("Geom_Ellipse") + .function("majorRadius", &Geom_Ellipse::MajorRadius) + .function("minorRadius", &Geom_Ellipse::MinorRadius) + .function("setMajorRadius", &Geom_Ellipse::SetMajorRadius) + .function("setMinorRadius", &Geom_Ellipse::SetMinorRadius) + .function("location", &Geom_Ellipse::Location) + .function("setLocation", &Geom_Ellipse::SetLocation) + .function("focus1", &Geom_Ellipse::Focus1) + .function("focus2", &Geom_Ellipse::Focus2) + ; + + class_>("Geom_Hyperbola") + .function("majorRadius", &Geom_Hyperbola::MajorRadius) + .function("minorRadius", &Geom_Hyperbola::MinorRadius) + .function("setMajorRadius", &Geom_Hyperbola::SetMajorRadius) + .function("setMinorRadius", &Geom_Hyperbola::SetMinorRadius) + .function("location", &Geom_Hyperbola::Location) + .function("setLocation", &Geom_Hyperbola::SetLocation) + .function("focal", &Geom_Hyperbola::Focal) + .function("focus1", &Geom_Hyperbola::Focus1) + .function("focus2", &Geom_Hyperbola::Focus2) + ; + + class_>("Geom_Parabola") + .function("focal", &Geom_Parabola::Focal) + .function("setFocal", &Geom_Parabola::SetFocal) + .function("focus", &Geom_Parabola::Focus) + .function("directrix", &Geom_Parabola::Directrix) + ; + + class_>("Geom_BoundedCurve") + .function("startPoint", &Geom_BoundedCurve::StartPoint) + .function("endPoint", &Geom_BoundedCurve::EndPoint) + ; + + class_>("Geom_Line") + .function("position", &Geom_Line::Position) + .function("setPosition", &Geom_Line::SetPosition) + .function("setLocation", &Geom_Line::SetLocation) + .function("setDirection", &Geom_Line::SetDirection) + ; + + class_>("Geom_TrimmedCurve") + .function("setTrim", &Geom_TrimmedCurve::SetTrim) + .function("basisCurve", &Geom_TrimmedCurve::BasisCurve) + ; + + class_>("Geom_OffsetCurve") + .function("offset", &Geom_OffsetCurve::Offset) + .function("basisCurve", &Geom_OffsetCurve::BasisCurve) + .function("direction", &Geom_OffsetCurve::Direction) + ; + + class_>("Geom_BezierCurve") + .function("insertPoleAfter", select_overload(&Geom_BezierCurve::InsertPoleAfter)) + .function("insertPoleAfterWithWeight", select_overload(&Geom_BezierCurve::InsertPoleAfter)) + .function("insertPoleBefore", select_overload(&Geom_BezierCurve::InsertPoleBefore)) + .function("insertPoleBeforeWithWeight", select_overload(&Geom_BezierCurve::InsertPoleBefore)) + .function("degree", &Geom_BezierCurve::Degree) + .function("weight", &Geom_BezierCurve::Weight) + .function("setWeight", &Geom_BezierCurve::SetWeight) + .function("nbPoles", &Geom_BezierCurve::NbPoles) + .function("getPoles", select_overload(&Geom_BezierCurve::Poles)) + .function("setPoles", select_overload(&Geom_BezierCurve::Poles)) + .function("pole", &Geom_BezierCurve::Pole) + .function("setPole", select_overload(&Geom_BezierCurve::SetPole)) + .function("setPoleWithWeight", select_overload(&Geom_BezierCurve::SetPole)) + .function("removePole", &Geom_BezierCurve::RemovePole) + ; + + class_>("Geom_BSplineCurve") + .function("insertKnot", &Geom_BSplineCurve::InsertKnot) + .function("degree", &Geom_BSplineCurve::Degree) + .function("nbPoles", &Geom_BSplineCurve::NbPoles) + .function("nbKnots", &Geom_BSplineCurve::NbKnots) + .function("knot", &Geom_BSplineCurve::Knot) + .function("setKnot", select_overload(&Geom_BSplineCurve::SetKnot)) + .function("weight", &Geom_BSplineCurve::Weight) + .function("setWeight", &Geom_BSplineCurve::SetWeight) + .function("getPoles", select_overload(&Geom_BSplineCurve::Poles)) + .function("setPoles", select_overload(&Geom_BSplineCurve::Poles)) + .function("pole", &Geom_BSplineCurve::Pole) + .function("setPole", select_overload(&Geom_BSplineCurve::SetPole)) + .function("setPoleWithWeight", select_overload(&Geom_BSplineCurve::SetPole)) + ; + + class_>("Geom_Surface") + .function("continuity", &Geom_Surface::Continuity) + .function("uIso", &Geom_Surface::UIso) + .function("vIso", &Geom_Surface::VIso) + .function("uPeriod", &Geom_Surface::UPeriod) + .function("vPeriod", &Geom_Surface::VPeriod) + .function("isUClosed", &Geom_Surface::IsUClosed) + .function("isVClosed", &Geom_Surface::IsVClosed) + .function("isUPeriodic", &Geom_Surface::IsUPeriodic) + .function("isVPeriodic", &Geom_Surface::IsVPeriodic) + .function("isCNu", &Geom_Surface::IsCNu) + .function("isCNv", &Geom_Surface::IsCNv) + .function("d0", &Geom_Surface::D0) + .function("d1", &Geom_Surface::D1) + .function("d2", &Geom_Surface::D2) + .function("d3", &Geom_Surface::D3) + .function("dn", &Geom_Surface::DN) + .function("value", &Geom_Surface::Value) ; - class_>("Geom_TrimmedCurve"); - class_>("Geom_Surface"); - class_("Handle_Geom_Curve") - .function("isNull", &Handle_Geom_Curve::IsNull) - .function("get", &Handle_Geom_Curve::get, allow_raw_pointers()) + class_>("GeomPlate_Surface") + .function("setBounds", &GeomPlate_Surface::SetBounds) ; - class_("Geom_TrimmedCurve") - .function("isNull", &Handle_Geom_Curve::IsNull) - .function("get", &Handle_Geom_Curve::get, allow_raw_pointers()) + class_>("Geom_ElementarySurface") + .function("setAxis", &Geom_ElementarySurface::SetAxis) + .function("setLocation", &Geom_ElementarySurface::SetLocation) + .function("axis", &Geom_ElementarySurface::Axis) + .function("location", &Geom_ElementarySurface::Location) + .function("position", &Geom_ElementarySurface::Position) + .function("setPosition", &Geom_ElementarySurface::SetPosition) ; + class_>("Geom_OffsetSurface") + .function("offset", &Geom_OffsetSurface::Offset) + .function("setOffsetValue", &Geom_OffsetSurface::SetOffsetValue) + .function("basisSurface", &Geom_OffsetSurface::BasisSurface) + .function("setBasisSurface", &Geom_OffsetSurface::SetBasisSurface) + ; + + class_>("Geom_SweptSurface") + .function("basisCurve", &Geom_SweptSurface::BasisCurve) + .function("direction", &Geom_SweptSurface::Direction) + ; + + class_>("ShapeExtend_CompositeSurface"); + + class_>("Geom_BSplineSurface"); + class_>("Geom_BezierSurface"); + class_>("Geom_BoundedSurface"); + class_>("Geom_RectangularTrimmedSurface") + .function("setTrim", select_overload(&Geom_RectangularTrimmedSurface::SetTrim)) + .function("setTrim2", select_overload(&Geom_RectangularTrimmedSurface::SetTrim)) + .function("basisSurface", &Geom_RectangularTrimmedSurface::BasisSurface) + ; + class_>("Geom_ConicalSurface") + .function("semiAngle", &Geom_ConicalSurface::SemiAngle) + .function("setSemiAngle", &Geom_ConicalSurface::SetSemiAngle) + .function("setRadius", &Geom_ConicalSurface::SetRadius) + .function("apex", &Geom_ConicalSurface::Apex) + .function("refRadius", &Geom_ConicalSurface::RefRadius) + ; + class_>("Geom_CylindricalSurface") + .function("radius", &Geom_CylindricalSurface::Radius) + .function("setRadius", &Geom_CylindricalSurface::SetRadius) + ; + class_>("Geom_Plane") + .function("pln", &Geom_Plane::Pln) + .function("setPln", &Geom_Plane::SetPln) + ; + class_>("Geom_SphericalSurface") + .function("radius", &Geom_SphericalSurface::Radius) + .function("setRadius", &Geom_SphericalSurface::SetRadius) + .function("area", &Geom_SphericalSurface::Area) + .function("volume", &Geom_SphericalSurface::Volume) + ; + class_>("Geom_ToroidalSurface") + .function("majorRadius", &Geom_ToroidalSurface::MajorRadius) + .function("minorRadius", &Geom_ToroidalSurface::MinorRadius) + .function("setMajorRadius", &Geom_ToroidalSurface::SetMajorRadius) + .function("setMinorRadius", &Geom_ToroidalSurface::SetMinorRadius) + .function("area", &Geom_ToroidalSurface::Area) + .function("volume", &Geom_ToroidalSurface::Volume) + ; + + class_>("Geom_SurfaceOfLinearExtrusion") + .function("direction", &Geom_SurfaceOfLinearExtrusion::Direction) + .function("setDirection", &Geom_SurfaceOfLinearExtrusion::SetDirection) + .function("setBasisCurve", &Geom_SurfaceOfLinearExtrusion::SetBasisCurve) + ; + class_>("Geom_SurfaceOfRevolution") + .function("location", &Geom_SurfaceOfRevolution::Location) + .function("setLocation", &Geom_SurfaceOfRevolution::SetLocation) + .function("setBasisCurve", &Geom_SurfaceOfRevolution::SetBasisCurve) + .function("direction", &Geom_SurfaceOfRevolution::Direction) + .function("setDirection", &Geom_SurfaceOfRevolution::SetDirection) + .function("referencePlane", &Geom_SurfaceOfRevolution::ReferencePlane) + ; + + REGISTER_HANDLE(Standard_Transient); + REGISTER_HANDLE(Geom_Geometry); + REGISTER_HANDLE(Geom_Curve); + REGISTER_HANDLE(Geom_Line); + REGISTER_HANDLE(Geom_TrimmedCurve); + REGISTER_HANDLE(Geom_Surface); + + class_("gp_Pnt") .constructor() .property("x", &gp_Pnt::X) @@ -122,32 +364,47 @@ EMSCRIPTEN_BINDINGS(opencascade) { .property("direct", &gp_Ax3::Direct) ; + class_("gp_Pln") + .constructor() + .constructor() + .property("location", &gp_Pln::Location) + .property("position", &gp_Pln::Position) + .property("axis", &gp_Pln::Axis) + .property("xAxis", &gp_Pln::XAxis) + .property("yAxis", &gp_Pln::YAxis) + ; + class_("gp_Trsf") .constructor() .function("value", &gp_Trsf::Value) .function("setValues", &gp_Trsf::SetValues) ; - class_("gp_Pln") - .constructor() - .function("location", &gp_Pln::Location) - .function("position", &gp_Pln::Position) - ; - class_("TopLoc_Location") .constructor() .function("transformation", &TopLoc_Location::Transformation) .function("inverted", &TopLoc_Location::Inverted) ; + class_("TopoDS") + .class_function("vertex", select_overload(&TopoDS::Vertex)) + .class_function("edge", select_overload(&TopoDS::Edge)) + .class_function("wire", select_overload(&TopoDS::Wire)) + .class_function("face", select_overload(&TopoDS::Face)) + .class_function("shell", select_overload(&TopoDS::Shell)) + .class_function("solid", select_overload(&TopoDS::Solid)) + .class_function("compound", select_overload(&TopoDS::Compound)) + .class_function("compsolid", select_overload(&TopoDS::CompSolid)) + ; + class_("TopoDS_Shape") .function("infinite", select_overload(&TopoDS_Shape::Infinite)) .function("isEqual", &TopoDS_Shape::IsEqual) .function("isNull", &TopoDS_Shape::IsNull) .function("isPartner", &TopoDS_Shape::IsPartner) .function("isSame", &TopoDS_Shape::IsSame) - .function("setLocation", select_overload(&TopoDS_Shape::Location)) - .function("getLocation", select_overload(&TopoDS_Shape::Location)) + .function("getLocation", select_overload(&TopoDS_Shape::Location)) + .function("setLocation", select_overload(&TopoDS_Shape::Location)) .function("nbChildren", &TopoDS_Shape::NbChildren) .function("nullify", &TopoDS_Shape::Nullify) .function("orientation", select_overload(&TopoDS_Shape::Orientation)) @@ -156,6 +413,13 @@ EMSCRIPTEN_BINDINGS(opencascade) { .function("shapeType", &TopoDS_Shape::ShapeType) ; + class_("TColgp_Array1OfPnt") + .constructor() + .function("value", select_overload(&TColgp_Array1OfPnt::Value)) + .function("setValue", select_overload(&TColgp_Array1OfPnt::SetValue)) + .function("length", &TColgp_Array1OfPnt::Length) + ; + class_>("TopoDS_Vertex"); class_>("TopoDS_Edge"); class_>("TopoDS_Wire"); @@ -165,8 +429,4 @@ EMSCRIPTEN_BINDINGS(opencascade) { class_>("TopoDS_Compound"); class_>("TopoDS_CompSolid"); - class_("BRep_Tool") - .class_function("pnt", &BRep_Tool::Pnt) - ; - } \ No newline at end of file diff --git a/cpp/src/shape.cpp b/cpp/src/shape.cpp index 97aa3a7a..c430bab4 100644 --- a/cpp/src/shape.cpp +++ b/cpp/src/shape.cpp @@ -1,29 +1,39 @@ #include "shared.hpp" #include #include -#include -#include #include #include +#include #include +#include +#include +#include #include #include #include #include #include +#include +#include #include +#include +#include #include -#include +#include #include +#include +#include +#include +#include +#include #include -#include -#include -#include + using namespace emscripten; class Shape { public: + static bool isClosed(const TopoDS_Shape& shape) { return BRep_Tool::IsClosed(shape); } @@ -41,12 +51,7 @@ class Shape { TopTools_IndexedMapOfShape indexShape; TopExp::MapShapes(shape, shapeType, indexShape); - std::vector shapes; - for (int i = 1; i <= indexShape.Extent(); i++) { - shapes.push_back(indexShape.FindKey(i)); - } - - return ShapeArray(val::array(shapes.begin(), shapes.end())); + return ShapeArray(val::array(indexShape.cbegin(), indexShape.cend())); } static TopoDS_Shape sectionSS(const TopoDS_Shape& shape, const TopoDS_Shape& otherShape) { @@ -59,16 +64,37 @@ class Shape { return section.Shape(); } + static TopoDS_Shape splitByEdgeOrWires(const TopoDS_Shape& shape, const ShapeArray& splitters) { + std::vector shapeVector = vecFromJSArray(splitters); + TopTools_SequenceOfShape shapes; + for (auto& s : shapeVector) { + shapes.Append(s); + } + + BRepFeat_SplitShape splitter(shape); + splitter.Add(shapes); + splitter.Build(); + return splitter.Shape(); + } + }; -struct EdgeIntersectResult { - NumberArray parameters; - PntArray points; +class Vertex { +public: + static Vector3 point(const TopoDS_Vertex& vertex) { + return Vector3::fromPnt(BRep_Tool::Pnt(vertex)); + } }; class Edge { public: - static double length(const TopoDS_Edge& edge) { + static TopoDS_Edge fromCurve (const Geom_Curve* curve) { + Handle_Geom_Curve handleCurve(curve); + BRepBuilderAPI_MakeEdge builder(handleCurve); + return builder.Edge(); + } + + static double curveLength(const TopoDS_Edge& edge) { BRepAdaptor_Curve curve(edge); return GCPnts_AbscissaPoint::Length(curve); } @@ -88,7 +114,7 @@ class Edge { } static TopoDS_Edge offset(const TopoDS_Edge& edge, const gp_Dir& dir, double offset) { - double start(0.0), end(0.0); + double start(0.0), end(0.0); auto curve = BRep_Tool::Curve(edge, start, end); Handle_Geom_TrimmedCurve trimmedCurve = new Geom_TrimmedCurve(curve, start, end); Handle_Geom_OffsetCurve offsetCurve = new Geom_OffsetCurve(trimmedCurve, offset, dir); @@ -96,22 +122,20 @@ class Edge { return builder.Edge(); } - static EdgeIntersectResult intersect(const TopoDS_Edge& edge, const TopoDS_Edge& otherEdge) { - std::vector points; - std::vector parameters; + static PointAndParameterArray intersect(const TopoDS_Edge& edge, const TopoDS_Edge& otherEdge) { + std::vector points; BRepExtrema_ExtCC cc(edge, otherEdge); if (cc.IsDone() && cc.NbExt() > 0 && !cc.IsParallel()) { for (int i = 1; i <= cc.NbExt(); i++) { - points.push_back(cc.PointOnE1(i)); - parameters.push_back(cc.ParameterOnE1(i)); + PointAndParameter pointAndParameter = { + Vector3::fromPnt(cc.PointOnE1(i)), + cc.ParameterOnE1(i), + }; + points.push_back(pointAndParameter); } } - EdgeIntersectResult result = { - NumberArray(val::array(parameters.begin(), parameters.end())), - PntArray(val::array(points.begin(), points.end())) - }; - return result; + return PointAndParameterArray(val::array(points)); } @@ -177,16 +201,17 @@ EMSCRIPTEN_BINDINGS(Shape) { .class_function("sectionSS", &Shape::sectionSS) .class_function("sectionSP", &Shape::sectionSP) .class_function("isClosed", &Shape::isClosed) + .class_function("splitByEdgeOrWires", &Shape::splitByEdgeOrWires) ; - class_("EdgeIntersectResult") - .property("parameters", &EdgeIntersectResult::parameters) - .property("points", &EdgeIntersectResult::points) + class_("Vertex") + .class_function("point", &Vertex::point) ; class_("Edge") + .class_function("fromCurve", &Edge::fromCurve, allow_raw_pointers()) .class_function("curve", &Edge::curve) - .function("length", &Edge::length) + .class_function("curveLength", &Edge::curveLength) .class_function("trim", &Edge::trim) .class_function("intersect", &Edge::intersect) .class_function("offset", &Edge::offset) @@ -194,10 +219,15 @@ EMSCRIPTEN_BINDINGS(Shape) { class_("Wire") .class_function("offset", &Wire::offset) + .class_function("makeFace", &Wire::makeFace) ; class_("Face") .class_function("offset", &Face::offset) + .class_function("outerWire", &Face::outerWire) + .class_function("surface", &Face::surface) + .class_function("normal", &Face::normal) + .class_function("curveOnSurface", &Face::curveOnSurface) ; } diff --git a/cpp/src/shapeFactory.cpp b/cpp/src/shapeFactory.cpp deleted file mode 100644 index 51f57f37..00000000 --- a/cpp/src/shapeFactory.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include -#include -#include -#include -#include - -using namespace emscripten; - -class ShapeFactory { -public: - static TopoDS_Shape makeBox(gp_Ax2 ax, double x, double y, double z) - { - BRepPrimAPI_MakeBox box(ax, x, y, z); - return box.Shape(); - } -}; - -EMSCRIPTEN_BINDINGS(ShapeFactory) -{ - class_("ShapeFactory") - .class_function("makeBox", &ShapeFactory::makeBox) - ; -} \ No newline at end of file diff --git a/cpp/src/shared.cpp b/cpp/src/shared.cpp index e2a8d504..e9959f9b 100644 --- a/cpp/src/shared.cpp +++ b/cpp/src/shared.cpp @@ -15,13 +15,56 @@ EMSCRIPTEN_BINDINGS(Shared) { register_type("BigInt64Array"); register_type("BigUint64Array"); + register_type("Array"); + register_type("Array"); + register_type("Array"); register_type("Array"); register_type("Array"); register_type("Array"); register_type("Array"); register_type("Array"); + + register_optional(); + register_optional(); + register_optional(); - value_object("Domain"); + value_object("Domain") + .field("start", &Domain::start) + .field("end", &Domain::end); + ; + + value_object("UV") + .field("u", &UV::u) + .field("v", &UV::v); + ; + + value_object("Vector3") + .field("x", &Vector3::x) + .field("y", &Vector3::y) + .field("z", &Vector3::z) + ; + + value_object("PointAndParameter") + .field("point", &PointAndParameter::point) + .field("parameter", &PointAndParameter::parameter) + ; + + value_object("Ax1") + .field("location", &Ax1::location) + .field("direction", &Ax1::direction) + ; + + value_object("Ax2") + .field("location", &Ax2::location) + .field("direction", &Ax2::direction) + .field("xDirection", &Ax2::xDirection) + ; + + value_object("Ax3") + .field("location", &Ax3::location) + .field("direction", &Ax3::direction) + .field("xDirection", &Ax3::xDirection) + ; } \ No newline at end of file diff --git a/cpp/src/shared.hpp b/cpp/src/shared.hpp index dc3e4773..bf781439 100644 --- a/cpp/src/shared.hpp +++ b/cpp/src/shared.hpp @@ -2,12 +2,127 @@ #include #include +#include +#include +#include +#include +#include +#include +#include + +#define STR(x) #x +#define REGISTER_HANDLE(T) \ + class_(STR(Handle_##T)) \ + .constructor() \ + .function("get", &Handle_##T::get, allow_raw_pointers()) \ + .function("isNull", &Handle_##T::IsNull) + +class Math { +public: + constexpr static const double PI = 3.14159265358979323846; + constexpr static const double PI_2 = PI * 2; + constexpr static const double PI_h = PI / 2; +}; struct Domain { double start; double end; }; +struct UV { + double u; + double v; +}; + +struct Vector3 { + double x; + double y; + double z; + + static gp_Pnt toPnt(const Vector3& p) { + return gp_Pnt(p.x, p.y, p.z); + } + + static Vector3 fromPnt(const gp_Pnt& p) { + return Vector3{p.X(), p.Y(), p.Z()}; + } + + static gp_Dir toDir(const Vector3& p) { + return gp_Dir(p.x, p.y, p.z); + } + + static Vector3 fromDir(const gp_Dir& p) { + return Vector3{p.X(), p.Y(), p.Z()}; + } + + static gp_Vec toVec(const Vector3& p) { + return gp_Vec(p.x, p.y, p.z); + } + + static Vector3 fromVec(const gp_Vec& p) { + return Vector3{p.X(), p.Y(), p.Z()}; + } +}; + +struct PointAndParameter { + Vector3 point; + double parameter; +}; + +struct Ax1 { + Vector3 location; + Vector3 direction; + + static gp_Ax1 toAx1(const Ax1& a) { + return gp_Ax1(Vector3::toPnt(a.location), Vector3::toDir(a.direction)); + } + + static Ax1 fromAx1(const gp_Ax1& a) { + return Ax1{Vector3::fromPnt(a.Location()), Vector3::fromDir(a.Direction())}; + } +}; + +struct Ax2 { + Vector3 location; + Vector3 direction; + Vector3 xDirection; + + static gp_Ax2 toAx2(const Ax2& a) { + return gp_Ax2(Vector3::toPnt(a.location), Vector3::toDir(a.direction), Vector3::toDir(a.xDirection)); + } + + static Ax2 fromAx2(const gp_Ax2& a) { + return Ax2{Vector3::fromPnt(a.Location()), Vector3::fromDir(a.Direction()), Vector3::fromDir(a.XDirection())}; + } +}; + +struct Ax3 { + Vector3 location; + Vector3 direction; + Vector3 xDirection; + + static gp_Ax2 toAx2(const Ax3& a) { + return gp_Ax2(Vector3::toPnt(a.location), Vector3::toDir(a.direction), Vector3::toDir(a.xDirection)); + } + + static Ax3 fromAx2(const gp_Ax2& a) { + return Ax3{Vector3::fromPnt(a.Location()), Vector3::fromDir(a.Direction()), Vector3::fromDir(a.XDirection())}; + } + + static gp_Ax3 toAx3(const Ax3& a) { + return gp_Ax3(Vector3::toPnt(a.location), Vector3::toDir(a.direction), Vector3::toDir(a.xDirection)); + } + + static Ax3 fromAx3(const gp_Ax3& a) { + return Ax3{Vector3::fromPnt(a.Location()), Vector3::fromDir(a.Direction()), Vector3::fromDir(a.XDirection())}; + } + + static gp_Pln toPln(const Ax3& a) { + return gp_Pln(toAx3(a)); + } + +}; + EMSCRIPTEN_DECLARE_VAL_TYPE(Int8Array) EMSCRIPTEN_DECLARE_VAL_TYPE(Int16Array) EMSCRIPTEN_DECLARE_VAL_TYPE(Int32Array) @@ -19,9 +134,12 @@ EMSCRIPTEN_DECLARE_VAL_TYPE(Float64Array) EMSCRIPTEN_DECLARE_VAL_TYPE(BigInt64Array) EMSCRIPTEN_DECLARE_VAL_TYPE(BigUint64Array) +EMSCRIPTEN_DECLARE_VAL_TYPE(Vector3Array) + EMSCRIPTEN_DECLARE_VAL_TYPE(NumberArray) EMSCRIPTEN_DECLARE_VAL_TYPE(EdgeArray) EMSCRIPTEN_DECLARE_VAL_TYPE(WireArray) EMSCRIPTEN_DECLARE_VAL_TYPE(FaceArray) EMSCRIPTEN_DECLARE_VAL_TYPE(ShapeArray) +EMSCRIPTEN_DECLARE_VAL_TYPE(PointAndParameterArray) EMSCRIPTEN_DECLARE_VAL_TYPE(PntArray) diff --git a/cpp/src/transient.cpp b/cpp/src/transient.cpp new file mode 100644 index 00000000..a75061b3 --- /dev/null +++ b/cpp/src/transient.cpp @@ -0,0 +1,28 @@ +#include +#include +#include + +using namespace emscripten; + + +class Transient { +public: + static bool isKind(const Standard_Transient *t, const std::string &name) { + return t->IsKind(name.c_str()); + } + + static bool isInstance(const Standard_Transient *t, const std::string &name) { + return t->IsInstance(name.c_str()); + } + +}; + + +EMSCRIPTEN_BINDINGS(Transient) { + + class_("Transient") + .class_function("isKind", &Transient::isKind, allow_raw_pointers()) + .class_function("isInstance", &Transient::isInstance, allow_raw_pointers()) + ; + +} \ No newline at end of file diff --git a/cpp/test/index.html b/cpp/test/index.html index c8303f23..cf39fb91 100644 --- a/cpp/test/index.html +++ b/cpp/test/index.html @@ -90,10 +90,11 @@ let initWasm = await import('../build/target/debug/chili-wasm.js'); let wasm = await initWasm.default(); test("test face mesh", (expect) => { - let point1 = new wasm.gp_Pnt(0, 0, 0); - let direction = new wasm.gp_Dir(0, 0, 1); - let ax2 = new wasm.gp_Ax2(point1, direction); - let box = wasm.ShapeFactory.makeBox(ax2, 1, 1, 1); + let location = { x: 0, y: 0, z: 0 }; + let direction = { x: 0, y: 0, z: 1 }; + let xDirection = { x: 1, y: 0, z: 0 }; + let ax3 = { location, direction, xDirection }; + let box = wasm.ShapeFactory.box(ax3, 1, 2, 3).shape; let mesh = new wasm.FaceMesher(box, 0.1); expect(mesh.getPosition().length).toBe(72); @@ -104,10 +105,11 @@ }) test("test edge mesh", (expect) => { - let point1 = new wasm.gp_Pnt(0, 0, 0); - let direction = new wasm.gp_Dir(0, 0, 1); - let ax2 = new wasm.gp_Ax2(point1, direction); - let box = wasm.ShapeFactory.makeBox(ax2, 1, 1, 1); + let location = { x: 0, y: 0, z: 0 }; + let direction = { x: 0, y: 0, z: 1 }; + let xDirection = { x: 1, y: 0, z: 0 }; + let ax3 = { location, direction, xDirection }; + let box = wasm.ShapeFactory.box(ax3, 1, 1, 1).shape; let mesh = new wasm.EdgeMesher(box, 0.1); expect(mesh.getPosition().length).toBe(72); @@ -117,10 +119,11 @@ test("test mesh 1000", (expect) => { let count = 0; for (let i = 0; i < 1000; i++) { - let point1 = new wasm.gp_Pnt(0, 0, 0); - let direction = new wasm.gp_Dir(0, 0, 1); - let ax2 = new wasm.gp_Ax2(point1, direction); - let box = wasm.ShapeFactory.makeBox(ax2, 10, 10, 10); + let location = { x: 0, y: 0, z: 0 }; + let direction = { x: 0, y: 0, z: 1 }; + let xDirection = { x: 1, y: 0, z: 0 }; + let ax2 = {location, direction, xDirection}; + let box = wasm.ShapeFactory.box(ax2, 10, 10, 10).shape; let fm = new wasm.FaceMesher(box, 0.1); let em = new wasm.EdgeMesher(box, 0.1); @@ -130,9 +133,6 @@ count += new Float32Array(fm.getNormal()).length; count += new Float32Array(fm.getUV()).length; - point1.delete(); - direction.delete(); - ax2.delete(); box.delete(); fm.delete(); em.delete(); @@ -142,15 +142,16 @@ }) test("test shape", (expect) => { - let point1 = new wasm.gp_Pnt(0, 0, 0); - let direction = new wasm.gp_Dir(0, 0, 1); - let ax2 = new wasm.gp_Ax2(point1, direction); - let box = wasm.ShapeFactory.makeBox(ax2, 1, 1, 1); + let location = { x: 0, y: 0, z: 0 }; + let direction = { x: 0, y: 0, z: 1 }; + let xDirection = { x: 1, y: 0, z: 0 }; + let ax3 = { location, direction, xDirection }; + let box = wasm.ShapeFactory.box(ax3, 1, 1, 1).shape; let edges = wasm.Shape.findSubShapes(box, wasm.TopAbs_ShapeEnum.TopAbs_EDGE); expect(edges.length).toBe(12); expect(edges[0].shapeType()).toBe(wasm.TopAbs_ShapeEnum.TopAbs_EDGE); - let curve = wasm.Edge.curve(wasm.TopoDS.edge(edges[0])) + let curve = wasm.Edge.curve(wasm.TopoDS.edge(edges[0])); let newEdge = wasm.Edge.fromCurve(curve.get()); expect(wasm.Edge.curveLength(newEdge)).toBe(1); diff --git a/packages/chili-builder/src/appBuilder.ts b/packages/chili-builder/src/appBuilder.ts index 17fcf22e..ef96b620 100644 --- a/packages/chili-builder/src/appBuilder.ts +++ b/packages/chili-builder/src/appBuilder.ts @@ -47,9 +47,9 @@ export class AppBuilder { this._inits.push(async () => { Logger.info("initializing new occ"); - let wasmModule = await import("chili-wasm"); - let wasm = await wasmModule.initWasm(); - (this._shapeFactory as any).wasm = wasm; // temporary test + let wasm = await import("chili-wasm"); + await wasm.initWasm(); + this._shapeFactory = new wasm.ShapeFactory(); }); return this; } diff --git a/packages/chili-core/src/shape/curve.ts b/packages/chili-core/src/shape/curve.ts index 90d52bf5..1daa5089 100644 --- a/packages/chili-core/src/shape/curve.ts +++ b/packages/chili-core/src/shape/curve.ts @@ -85,7 +85,6 @@ export interface ICircle extends IConic { } export interface IEllipse extends IConic { - area(): number; center: XYZ; get focus1(): XYZ; get focus2(): XYZ; diff --git a/packages/chili-core/src/shape/shape.ts b/packages/chili-core/src/shape/shape.ts index 239798ac..76564349 100644 --- a/packages/chili-core/src/shape/shape.ts +++ b/packages/chili-core/src/shape/shape.ts @@ -36,7 +36,6 @@ export interface IShape extends IDisposable { orientation(): Orientation; findAncestor(ancestorType: ShapeType, fromShape: IShape): IShape[]; findSubShapes(subshapeType: ShapeType): IShape[]; - iterSubShapes(shapeType: ShapeType, unique: boolean): IterableIterator; section(shape: IShape | Plane): IShape; split(edges: (IEdge | IWire)[]): IShape; } diff --git a/packages/chili-core/src/shape/surface.ts b/packages/chili-core/src/shape/surface.ts index d248a5e7..85c88f91 100644 --- a/packages/chili-core/src/shape/surface.ts +++ b/packages/chili-core/src/shape/surface.ts @@ -81,7 +81,6 @@ export interface ISurface extends IGeometry { }; dn(u: number, v: number, nu: number, nv: number): XYZ; value(u: number, v: number): XYZ; - makeFace(): IFace; } export interface IPlateSurface extends ISurface { diff --git a/packages/chili-geo/src/mesh.ts b/packages/chili-geo/src/mesh.ts index a1ec782d..ff30e5e7 100644 --- a/packages/chili-geo/src/mesh.ts +++ b/packages/chili-geo/src/mesh.ts @@ -12,6 +12,7 @@ export class MeshUtils { let [indiceStart, indiceEnd] = [minMax.min, minMax.max + 1]; let positions = mesh.positions.slice(indiceStart * 3, indiceEnd * 3); + let uvs = mesh.uvs.slice(indiceStart * 2, indiceEnd * 2); let normals = mesh.normals.slice(indiceStart * 3, indiceEnd * 3); indices = indices.map((i) => i - indiceStart); @@ -19,6 +20,9 @@ export class MeshUtils { positions, normals, indices, + uvs, + groups: [], + color: mesh.color, }; } diff --git a/packages/chili-geo/src/utils.ts b/packages/chili-geo/src/utils.ts index a9bf0b67..44ad70c0 100644 --- a/packages/chili-geo/src/utils.ts +++ b/packages/chili-geo/src/utils.ts @@ -32,7 +32,7 @@ export class GeoUtils { } let firstEdge: IEdge | undefined = undefined; - for (const edge of wire.iterSubShapes(ShapeType.Edge, true)) { + for (const edge of wire.findSubShapes(ShapeType.Edge)) { firstEdge = edge as IEdge; break; } @@ -42,7 +42,7 @@ export class GeoUtils { static findNextEdge(wire: IWire, edge: IEdge): Result { let curve = edge.curve(); let point = curve.value(curve.lastParameter()); - for (const e of wire.iterSubShapes(ShapeType.Edge, true)) { + for (const e of wire.findSubShapes(ShapeType.Edge)) { if (e.isEqual(edge)) continue; let testCurve = (e as IEdge).curve(); if ( diff --git a/packages/chili-occ/src/occShape.ts b/packages/chili-occ/src/occShape.ts index 3e07ae80..4ae078ef 100644 --- a/packages/chili-occ/src/occShape.ts +++ b/packages/chili-occ/src/occShape.ts @@ -137,13 +137,6 @@ export class OccShape implements IShape { return result; } - *iterSubShapes(shapeType: ShapeType, unique: boolean = false): IterableIterator { - let iter = OccHelps.iterShapes(this.shape, OccHelps.getShapeEnum(shapeType), unique); - for (const it of iter) { - yield OccHelps.wrapShape(it); - } - } - orientation(): Orientation { return OccHelps.getOrientation(this._shape); } diff --git a/packages/chili-occ/test/occ.test.ts b/packages/chili-occ/test/occ.test.ts index a4de6410..2b7f9314 100644 --- a/packages/chili-occ/test/occ.test.ts +++ b/packages/chili-occ/test/occ.test.ts @@ -58,20 +58,6 @@ describe("shape test", () => { expect(box.findSubShapes(ShapeType.Shell).length).toBe(1); expect(box.findSubShapes(ShapeType.Shell)[0].shapeType).toBe(ShapeType.Shell); expect(box.findSubShapes(ShapeType.Shape).length).toBe(0); - - let v1s: any[] = []; - let iter = box.iterSubShapes(ShapeType.Vertex); - for (const i of iter) { - v1s.push(i); - } - expect(v1s.length).toBe(48); - - let v2s: any[] = []; - let iter2 = box.iterSubShapes(ShapeType.Vertex, true); - for (const i of iter2) { - v2s.push(i); - } - expect(v2s.length).toBe(8); }); test("test ancestors", () => { diff --git a/packages/chili-three/src/threeGeometry.ts b/packages/chili-three/src/threeGeometry.ts index 45924d5d..c543c4a2 100644 --- a/packages/chili-three/src/threeGeometry.ts +++ b/packages/chili-three/src/threeGeometry.ts @@ -24,6 +24,7 @@ import { LineSegments2 } from "three/examples/jsm/lines/LineSegments2"; import { LineSegmentsGeometry } from "three/examples/jsm/lines/LineSegmentsGeometry"; import { ThreeHelper } from "./threeHelper"; import { ThreeVisualContext } from "./threeVisualContext"; +import { ThreeGeometryFactory } from "./threeGeometryFactory"; export class ThreeGeometry extends Object3D implements IVisualGeometry { private _faceMaterial: Material; @@ -122,22 +123,13 @@ export class ThreeGeometry extends Object3D implements IVisualGeometry { } private initEdges(data: EdgeMeshData) { - let buff = new LineSegmentsGeometry(); - buff.setPositions(data.positions); - buff.computeBoundingBox(); - + let buff = ThreeGeometryFactory.createEdgeBufferGeometry(data); this._edges = new LineSegments2(buff, this._edgeMaterial); this.add(this._edges); } private initFaces(data: FaceMeshData) { - let buff = new BufferGeometry(); - buff.setAttribute("position", new Float32BufferAttribute(data.positions, 3)); - buff.setAttribute("normal", new Float32BufferAttribute(data.normals, 3)); - buff.setAttribute("uv", new Float32BufferAttribute(data.uvs, 2)); - buff.setIndex(data.indices); - buff.computeBoundingBox(); - + let buff = ThreeGeometryFactory.createFaceBufferGeometry(data); this._faces = new Mesh(buff, this._faceMaterial); this.add(this._faces); } @@ -174,10 +166,7 @@ export class ThreeGeometry extends Object3D implements IVisualGeometry { let mesh = MeshUtils.subFace(this.geometryEngity.shape.ok().mesh.faces!, index); if (!mesh) return undefined; - let buff = new BufferGeometry(); - buff.setAttribute("position", new Float32BufferAttribute(mesh.positions, 3)); - buff.setAttribute("normal", new Float32BufferAttribute(mesh.normals, 3)); - buff.setIndex(mesh.indices); + let buff = ThreeGeometryFactory.createFaceBufferGeometry(mesh); buff.applyMatrix4(this.matrixWorld); return new Mesh(buff, this._faceMaterial); diff --git a/packages/chili-three/src/threeGeometryFactory.ts b/packages/chili-three/src/threeGeometryFactory.ts index cba2b64c..0e126754 100644 --- a/packages/chili-three/src/threeGeometryFactory.ts +++ b/packages/chili-three/src/threeGeometryFactory.ts @@ -19,7 +19,7 @@ import { LineSegmentsGeometry } from "three/examples/jsm/lines/LineSegmentsGeome export class ThreeGeometryFactory { static createVertexGeometry(data: VertexMeshData) { let buff = new BufferGeometry(); - buff.setAttribute("position", new Float32BufferAttribute(data.positions, 3)); + buff.setAttribute("position", new BufferAttribute(new Float32Array(data.positions), 3)); let color = data.color as number; let material = new PointsMaterial({ size: data.size, @@ -31,12 +31,7 @@ export class ThreeGeometryFactory { } static createFaceGeometry(data: FaceMeshData) { - let buff = new BufferGeometry(); - buff.setAttribute("position", new BufferAttribute(new Float32Array(data.positions), 3)); - buff.setAttribute("normal", new BufferAttribute(new Float32Array(data.normals), 3)); - buff.setAttribute("uv", new BufferAttribute(new Float32Array(data.uvs), 2)); - buff.setIndex(new BufferAttribute(new Uint32Array(data.indices), 1)); - buff.computeBoundingBox(); + let buff = ThreeGeometryFactory.createFaceBufferGeometry(data); let material = new MeshLambertMaterial({ side: DoubleSide }); if (typeof data.color === "number") { material.color.set(data.color); @@ -48,10 +43,18 @@ export class ThreeGeometryFactory { return new Mesh(buff, material); } - static createEdgeGeometry(data: EdgeMeshData) { - let buff = new LineSegmentsGeometry(); - buff.setPositions(new Float32Array(data.positions)); + static createFaceBufferGeometry(data: FaceMeshData) { + let buff = new BufferGeometry(); + buff.setAttribute("position", new BufferAttribute(new Float32Array(data.positions), 3)); + buff.setAttribute("normal", new BufferAttribute(new Float32Array(data.normals), 3)); + buff.setAttribute("uv", new BufferAttribute(new Float32Array(data.uvs), 2)); + buff.setIndex(data.indices); + buff.computeBoundingBox(); + return buff; + } + static createEdgeGeometry(data: EdgeMeshData) { + let buff = this.createEdgeBufferGeometry(data); let color = data.color as number; let linewidth = data.lineWidth ?? 1; let material = @@ -76,4 +79,11 @@ export class ThreeGeometryFactory { }); return new LineSegments2(buff, material).computeLineDistances(); } + + static createEdgeBufferGeometry(data: EdgeMeshData) { + let buff = new LineSegmentsGeometry(); + buff.setPositions(data.positions); + buff.computeBoundingBox(); + return buff; + } } diff --git a/packages/chili-three/test/testEdge.ts b/packages/chili-three/test/testEdge.ts index e8472681..1b34bb32 100644 --- a/packages/chili-three/test/testEdge.ts +++ b/packages/chili-three/test/testEdge.ts @@ -50,10 +50,6 @@ export class TestEdge implements IEdge { throw new Error("Method not implemented."); } - iterSubShapes(shapeType: ShapeType, unique: boolean): IterableIterator { - throw new Error("Method not implemented."); - } - findSubShapes(subshapeType: ShapeType): IShape[] { throw new Error("Method not implemented."); } diff --git a/packages/chili-wasm/lib/chili-wasm.d.ts b/packages/chili-wasm/lib/chili-wasm.d.ts index b5b2003c..f67a0c9e 100644 --- a/packages/chili-wasm/lib/chili-wasm.d.ts +++ b/packages/chili-wasm/lib/chili-wasm.d.ts @@ -14,14 +14,45 @@ declare namespace RuntimeExports { } interface WasmModule {} +type EmbindString = ArrayBuffer | Uint8Array | Uint8ClampedArray | Int8Array | string; +export interface Converter { + delete(): void; +} + +export interface ShapeResult { + isOk: boolean; + error: EmbindString; + shape: TopoDS_Shape; + delete(): void; +} + +export interface ShapeFactory { + delete(): void; +} + +export interface Curve { + delete(): void; +} + +export type SurfaceBounds = { + u1: number; + u2: number; + v1: number; + v2: number; +}; + +export interface Surface { + delete(): void; +} + export interface FaceMesher { getFaceSize(): number; getFace(_0: number): TopoDS_Face; - getIndex(): Uint32Array; - getGroups(): Uint32Array; - getPosition(): Float32Array; - getNormal(): Float32Array; - getUV(): Float32Array; + getPosition(): Array; + getNormal(): Array; + getUV(): Array; + getIndex(): Array; + getGroups(): Array; getFaces(): Array; delete(): void; } @@ -29,12 +60,24 @@ export interface FaceMesher { export interface EdgeMesher { getEdgeSize(): number; getEdge(_0: number): TopoDS_Edge; - getGroups(): Uint32Array; - getPosition(): Float32Array; + getPosition(): Array; + getGroups(): Array; getEdges(): Array; delete(): void; } +export interface GeomAbs_ShapeValue { + value: T; +} +export type GeomAbs_Shape = + | GeomAbs_ShapeValue<0> + | GeomAbs_ShapeValue<2> + | GeomAbs_ShapeValue<4> + | GeomAbs_ShapeValue<5> + | GeomAbs_ShapeValue<6> + | GeomAbs_ShapeValue<1> + | GeomAbs_ShapeValue<3>; + export interface GeomAbs_JoinTypeValue { value: T; } @@ -67,10 +110,12 @@ export type TopAbs_Orientation = | TopAbs_OrientationValue<3>; export interface Standard_Transient { + getRefCount(): number; delete(): void; } export interface Geom_Geometry extends Standard_Transient { + copy(): Handle_Geom_Geometry; delete(): void; } @@ -79,27 +124,306 @@ export interface Geom_Curve extends Geom_Geometry { isPeriodic(): boolean; period(): number; reverse(): void; + isCN(_0: number): boolean; firstParameter(): number; lastParameter(): number; + continutity(): GeomAbs_Shape; + reversed(): Handle_Geom_Curve; + d0(_0: number, _1: gp_Pnt): void; value(_0: number): gp_Pnt; d1(_0: number, _1: gp_Pnt, _2: gp_Vec): void; d2(_0: number, _1: gp_Pnt, _2: gp_Vec, _3: gp_Vec): void; d3(_0: number, _1: gp_Pnt, _2: gp_Vec, _3: gp_Vec, _4: gp_Vec): void; - d4(_0: number, _1: number): gp_Vec; + dn(_0: number, _1: number): gp_Vec; + delete(): void; +} + +export interface Geom_Conic extends Geom_Curve { + eccentricity(): number; + location(): gp_Pnt; + setLocation(_0: gp_Pnt): void; + location(): gp_Pnt; + setLocation(_0: gp_Pnt): void; + location(): gp_Pnt; + setLocation(_0: gp_Pnt): void; + axis(): gp_Ax1; + xAxis(): gp_Ax1; + yAxis(): gp_Ax1; + delete(): void; +} + +export interface Geom_Circle extends Geom_Conic { + radius(): number; + setRadius(_0: number): void; + delete(): void; +} + +export interface Geom_Ellipse extends Geom_Conic { + majorRadius(): number; + minorRadius(): number; + setMajorRadius(_0: number): void; + setMinorRadius(_0: number): void; + focus1(): gp_Pnt; + focus2(): gp_Pnt; + delete(): void; +} + +export interface Geom_Hyperbola extends Geom_Conic { + majorRadius(): number; + minorRadius(): number; + setMajorRadius(_0: number): void; + setMinorRadius(_0: number): void; + focal(): number; + focus1(): gp_Pnt; + focus2(): gp_Pnt; + delete(): void; +} + +export interface Geom_Parabola extends Geom_Conic { + focal(): number; + setFocal(_0: number): void; + focus(): gp_Pnt; + directrix(): gp_Ax1; + delete(): void; +} + +export interface Geom_BoundedCurve extends Geom_Curve { + startPoint(): gp_Pnt; + endPoint(): gp_Pnt; + delete(): void; +} + +export interface Geom_Line extends Geom_Curve { + setLocation(_0: gp_Pnt): void; + setDirection(_0: gp_Dir): void; + position(): gp_Ax1; + setPosition(_0: gp_Ax1): void; + delete(): void; +} + +export interface Geom_TrimmedCurve extends Geom_BoundedCurve { + setTrim(_0: number, _1: number, _2: boolean, _3: boolean): void; + basisCurve(): Handle_Geom_Curve; delete(): void; } -export interface Geom_TrimmedCurve extends Geom_Curve { +export interface Geom_OffsetCurve extends Geom_Curve { + offset(): number; + basisCurve(): Handle_Geom_Curve; + direction(): gp_Dir; + delete(): void; +} + +export interface Geom_BezierCurve extends Geom_BoundedCurve { + degree(): number; + weight(_0: number): number; + setWeight(_0: number, _1: number): void; + nbPoles(): number; + removePole(_0: number): void; + insertPoleAfter(_0: number, _1: gp_Pnt): void; + insertPoleAfterWithWeight(_0: number, _1: gp_Pnt, _2: number): void; + insertPoleBefore(_0: number, _1: gp_Pnt): void; + insertPoleBeforeWithWeight(_0: number, _1: gp_Pnt, _2: number): void; + pole(_0: number): gp_Pnt; + setPole(_0: number, _1: gp_Pnt): void; + setPoleWithWeight(_0: number, _1: gp_Pnt, _2: number): void; + getPoles(): TColgp_Array1OfPnt; + setPoles(_0: TColgp_Array1OfPnt): void; + delete(): void; +} + +export interface Geom_BSplineCurve extends Geom_BoundedCurve { + insertKnot(_0: number, _1: number, _2: number, _3: boolean): void; + degree(): number; + nbPoles(): number; + nbKnots(): number; + knot(_0: number): number; + setKnot(_0: number, _1: number): void; + weight(_0: number): number; + setWeight(_0: number, _1: number): void; + pole(_0: number): gp_Pnt; + setPole(_0: number, _1: gp_Pnt): void; + setPoleWithWeight(_0: number, _1: gp_Pnt, _2: number): void; + getPoles(): TColgp_Array1OfPnt; + setPoles(_0: TColgp_Array1OfPnt): void; delete(): void; } export interface Geom_Surface extends Geom_Geometry { + continuity(): GeomAbs_Shape; + uPeriod(): number; + vPeriod(): number; + isUClosed(): boolean; + isVClosed(): boolean; + isUPeriodic(): boolean; + isVPeriodic(): boolean; + isCNu(_0: number): boolean; + isCNv(_0: number): boolean; + uIso(_0: number): Handle_Geom_Curve; + vIso(_0: number): Handle_Geom_Curve; + d0(_0: number, _1: number, _2: gp_Pnt): void; + value(_0: number, _1: number): gp_Pnt; + d1(_0: number, _1: number, _2: gp_Pnt, _3: gp_Vec, _4: gp_Vec): void; + d2(_0: number, _1: number, _2: gp_Pnt, _3: gp_Vec, _4: gp_Vec, _5: gp_Vec, _6: gp_Vec, _7: gp_Vec): void; + d3( + _0: number, + _1: number, + _2: gp_Pnt, + _3: gp_Vec, + _4: gp_Vec, + _5: gp_Vec, + _6: gp_Vec, + _7: gp_Vec, + _8: gp_Vec, + _9: gp_Vec, + _10: gp_Vec, + _11: gp_Vec, + ): void; + dn(_0: number, _1: number, _2: number, _3: number): gp_Vec; delete(): void; } -export interface Handle_Geom_Curve { +export interface GeomPlate_Surface extends Geom_Surface { + setBounds(_0: number, _1: number, _2: number, _3: number): void; + delete(): void; +} + +export interface Geom_ElementarySurface extends Geom_Surface { + setLocation(_0: gp_Pnt): void; + location(): gp_Pnt; + setAxis(_0: gp_Ax1): void; + axis(): gp_Ax1; + position(): gp_Ax3; + setPosition(_0: gp_Ax3): void; + delete(): void; +} + +export interface Geom_OffsetSurface extends Geom_Surface { + offset(): number; + setOffsetValue(_0: number): void; + basisSurface(): Handle_Geom_Surface; + setBasisSurface(_0: Handle_Geom_Surface, _1: boolean): void; + delete(): void; +} + +export interface Geom_SweptSurface extends Geom_Surface { + basisCurve(): Handle_Geom_Curve; + direction(): gp_Dir; + direction(): gp_Dir; + direction(): gp_Dir; + delete(): void; +} + +export interface ShapeExtend_CompositeSurface extends Geom_Surface { + delete(): void; +} + +export interface Geom_BSplineSurface extends Geom_Surface { + delete(): void; +} + +export interface Geom_BezierSurface extends Geom_Surface { + delete(): void; +} + +export interface Geom_BoundedSurface extends Geom_Surface { + delete(): void; +} + +export interface Geom_RectangularTrimmedSurface extends Geom_BoundedSurface { + setTrim(_0: number, _1: number, _2: number, _3: number, _4: boolean, _5: boolean): void; + setTrim2(_0: number, _1: number, _2: boolean, _3: boolean): void; + basisSurface(): Handle_Geom_Surface; + delete(): void; +} + +export interface Geom_ConicalSurface extends Geom_ElementarySurface { + semiAngle(): number; + setSemiAngle(_0: number): void; + setRadius(_0: number): void; + refRadius(): number; + apex(): gp_Pnt; + delete(): void; +} + +export interface Geom_CylindricalSurface extends Geom_ElementarySurface { + radius(): number; + setRadius(_0: number): void; + delete(): void; +} + +export interface Geom_Plane extends Geom_ElementarySurface { + pln(): gp_Pln; + setPln(_0: gp_Pln): void; + delete(): void; +} + +export interface Geom_SphericalSurface extends Geom_ElementarySurface { + radius(): number; + setRadius(_0: number): void; + area(): number; + volume(): number; + delete(): void; +} + +export interface Geom_ToroidalSurface extends Geom_ElementarySurface { + majorRadius(): number; + minorRadius(): number; + setMajorRadius(_0: number): void; + setMinorRadius(_0: number): void; + area(): number; + volume(): number; + delete(): void; +} + +export interface Geom_SurfaceOfLinearExtrusion extends Geom_SweptSurface { + setBasisCurve(_0: Handle_Geom_Curve): void; + setDirection(_0: gp_Dir): void; + delete(): void; +} + +export interface Geom_SurfaceOfRevolution extends Geom_SweptSurface { + setBasisCurve(_0: Handle_Geom_Curve): void; + location(): gp_Pnt; + setLocation(_0: gp_Pnt): void; + setDirection(_0: gp_Dir): void; + referencePlane(): gp_Ax2; + delete(): void; +} + +export interface Handle_Standard_Transient { + get(): Standard_Transient | null; isNull(): boolean; + delete(): void; +} + +export interface Handle_Geom_Geometry { + get(): Geom_Geometry | null; + isNull(): boolean; + delete(): void; +} + +export interface Handle_Geom_Curve { get(): Geom_Curve | null; + isNull(): boolean; + delete(): void; +} + +export interface Handle_Geom_Line { + get(): Geom_Line | null; + isNull(): boolean; + delete(): void; +} + +export interface Handle_Geom_TrimmedCurve { + get(): Geom_TrimmedCurve | null; + isNull(): boolean; + delete(): void; +} + +export interface Handle_Geom_Surface { + get(): Geom_Surface | null; + isNull(): boolean; delete(): void; } @@ -147,6 +471,15 @@ export interface gp_Ax3 { delete(): void; } +export interface gp_Pln { + readonly location: gp_Pnt; + readonly position: gp_Ax3; + readonly axis: gp_Ax1; + readonly xAxis: gp_Ax1; + readonly yAxis: gp_Ax1; + delete(): void; +} + export interface gp_Trsf { value(_0: number, _1: number): number; setValues( @@ -166,26 +499,24 @@ export interface gp_Trsf { delete(): void; } -export interface gp_Pln { - location(): gp_Pnt; - position(): gp_Ax3; - delete(): void; -} - export interface TopLoc_Location { transformation(): gp_Trsf; inverted(): TopLoc_Location; delete(): void; } +export interface TopoDS { + delete(): void; +} + export interface TopoDS_Shape { infinite(): boolean; isEqual(_0: TopoDS_Shape): boolean; isNull(): boolean; isPartner(_0: TopoDS_Shape): boolean; isSame(_0: TopoDS_Shape): boolean; - setLocation(): TopLoc_Location; - getLocation(_0: TopLoc_Location, _1: boolean): void; + getLocation(): TopLoc_Location; + setLocation(_0: TopLoc_Location, _1: boolean): void; nbChildren(): number; nullify(): void; orientation(): TopAbs_Orientation; @@ -195,12 +526,18 @@ export interface TopoDS_Shape { delete(): void; } +export interface TColgp_Array1OfPnt { + value(_0: number): gp_Pnt; + setValue(_0: number, _1: gp_Pnt): void; + length(): number; + delete(): void; +} + export interface TopoDS_Vertex extends TopoDS_Shape { delete(): void; } export interface TopoDS_Edge extends TopoDS_Shape { - length(): number; delete(): void; } @@ -228,17 +565,11 @@ export interface TopoDS_CompSolid extends TopoDS_Shape { delete(): void; } -export interface BRep_Tool { - delete(): void; -} - export interface Shape { delete(): void; } -export interface EdgeIntersectResult { - parameters: Array; - points: Array; +export interface Vertex { delete(): void; } @@ -254,15 +585,117 @@ export interface Face { delete(): void; } -export interface ShapeFactory { +export type Domain = { + start: number; + end: number; +}; + +export type UV = { + u: number; + v: number; +}; + +export type Vector3 = { + x: number; + y: number; + z: number; +}; + +export type ProjectPointResult = { + point: Vector3; + distance: number; + parameter: number; +}; + +export type ExtremaCCResult = { + distance: number; + p1: Vector3; + p2: Vector3; + isParallel: boolean; + u1: number; + u2: number; +}; + +export type PointAndParameter = { + point: Vector3; + parameter: number; +}; + +export type Ax1 = { + location: Vector3; + direction: Vector3; +}; + +export type Ax2 = { + location: Vector3; + direction: Vector3; + xDirection: Vector3; +}; + +export type Ax3 = { + location: Vector3; + direction: Vector3; + xDirection: Vector3; +}; + +export interface Transient { delete(): void; } -export type Domain = {}; - interface EmbindModule { + Converter: { convertToBrep(_0: TopoDS_Shape): string; convertFromBrep(_0: EmbindString): TopoDS_Shape }; + ShapeResult: {}; + ShapeFactory: { + makeThickSolidBySimple(_0: TopoDS_Shape, _1: number): ShapeResult; + sweep(_0: TopoDS_Shape, _1: TopoDS_Wire): ShapeResult; + polygon(_0: Array): ShapeResult; + bezier(_0: Array, _1: Array): ShapeResult; + makeThickSolidByJoin(_0: TopoDS_Shape, _1: Array, _2: number): ShapeResult; + booleanCommon(_0: Array, _1: Array): ShapeResult; + booleanCut(_0: Array, _1: Array): ShapeResult; + booleanFuse(_0: Array, _1: Array): ShapeResult; + combine(_0: Array): ShapeResult; + wire(_0: Array): ShapeResult; + face(_0: Array): ShapeResult; + prism(_0: TopoDS_Shape, _1: Vector3): ShapeResult; + circle(_0: Vector3, _1: Vector3, _2: number): ShapeResult; + arc(_0: Vector3, _1: Vector3, _2: Vector3, _3: number): ShapeResult; + point(_0: Vector3): ShapeResult; + line(_0: Vector3, _1: Vector3): ShapeResult; + revolve(_0: TopoDS_Shape, _1: Ax1, _2: number): ShapeResult; + box(_0: Ax3, _1: number, _2: number, _3: number): ShapeResult; + rect(_0: Ax3, _1: number, _2: number): ShapeResult; + }; + Curve: { + curveLength(_0: Geom_Curve | null): number; + trim(_0: Geom_Curve | null, _1: number, _2: number): Handle_Geom_TrimmedCurve; + uniformAbscissaWithCount(_0: Geom_Curve | null, _1: number): Array; + uniformAbscissaWithLength(_0: Geom_Curve | null, _1: number): Array; + nearestExtremaCC(_0: Geom_Curve | null, _1: Geom_Curve | null): ExtremaCCResult | undefined; + makeLine(_0: Vector3, _1: Vector3): Handle_Geom_Line; + projectOrNearest(_0: Geom_Curve | null, _1: Vector3): ProjectPointResult; + parameter(_0: Geom_Curve | null, _1: Vector3, _2: number): number | undefined; + projects(_0: Geom_Curve | null, _1: Vector3): Array; + }; + Surface: { + isPlanar(_0: Geom_Surface | null): boolean; + bounds(_0: Geom_Surface | null): SurfaceBounds; + projectCurve(_0: Geom_Surface | null, _1: Geom_Curve | null): Handle_Geom_Curve; + projectPoint(_0: Geom_Surface | null, _1: Vector3): Array; + parameters(_0: Geom_Surface | null, _1: Vector3, _2: number): UV | undefined; + nearestPoint(_0: Geom_Surface | null, _1: Vector3): PointAndParameter | undefined; + }; FaceMesher: { new (_0: TopoDS_Shape, _1: number): FaceMesher }; EdgeMesher: { new (_0: TopoDS_Shape, _1: number): EdgeMesher }; + GeomAbs_Shape: { + GeomAbs_C0: GeomAbs_ShapeValue<0>; + GeomAbs_C1: GeomAbs_ShapeValue<2>; + GeomAbs_C2: GeomAbs_ShapeValue<4>; + GeomAbs_C3: GeomAbs_ShapeValue<5>; + GeomAbs_CN: GeomAbs_ShapeValue<6>; + GeomAbs_G1: GeomAbs_ShapeValue<1>; + GeomAbs_G2: GeomAbs_ShapeValue<3>; + }; GeomAbs_JoinType: { GeomAbs_Arc: GeomAbs_JoinTypeValue<0>; GeomAbs_Intersection: GeomAbs_JoinTypeValue<2>; @@ -288,19 +721,61 @@ interface EmbindModule { Standard_Transient: {}; Geom_Geometry: {}; Geom_Curve: {}; + Geom_Conic: {}; + Geom_Circle: {}; + Geom_Ellipse: {}; + Geom_Hyperbola: {}; + Geom_Parabola: {}; + Geom_BoundedCurve: {}; + Geom_Line: {}; Geom_TrimmedCurve: {}; + Geom_OffsetCurve: {}; + Geom_BezierCurve: {}; + Geom_BSplineCurve: {}; Geom_Surface: {}; - Handle_Geom_Curve: {}; + GeomPlate_Surface: {}; + Geom_ElementarySurface: {}; + Geom_OffsetSurface: {}; + Geom_SweptSurface: {}; + ShapeExtend_CompositeSurface: {}; + Geom_BSplineSurface: {}; + Geom_BezierSurface: {}; + Geom_BoundedSurface: {}; + Geom_RectangularTrimmedSurface: {}; + Geom_ConicalSurface: {}; + Geom_CylindricalSurface: {}; + Geom_Plane: {}; + Geom_SphericalSurface: {}; + Geom_ToroidalSurface: {}; + Geom_SurfaceOfLinearExtrusion: {}; + Geom_SurfaceOfRevolution: {}; + Handle_Standard_Transient: { new (_0: Standard_Transient | null): Handle_Standard_Transient }; + Handle_Geom_Geometry: { new (_0: Geom_Geometry | null): Handle_Geom_Geometry }; + Handle_Geom_Curve: { new (_0: Geom_Curve | null): Handle_Geom_Curve }; + Handle_Geom_Line: { new (_0: Geom_Line | null): Handle_Geom_Line }; + Handle_Geom_TrimmedCurve: { new (_0: Geom_TrimmedCurve | null): Handle_Geom_TrimmedCurve }; + Handle_Geom_Surface: { new (_0: Geom_Surface | null): Handle_Geom_Surface }; gp_Pnt: { new (_0: number, _1: number, _2: number): gp_Pnt }; gp_Vec: { new (_0: number, _1: number, _2: number): gp_Vec }; gp_Dir: { new (_0: number, _1: number, _2: number): gp_Dir }; gp_Ax1: { new (_0: gp_Pnt, _1: gp_Dir): gp_Ax1 }; gp_Ax2: { new (_0: gp_Pnt, _1: gp_Dir): gp_Ax2; new (_0: gp_Pnt, _1: gp_Dir, _2: gp_Dir): gp_Ax2 }; gp_Ax3: { new (_0: gp_Pnt, _1: gp_Dir, _2: gp_Dir): gp_Ax3; new (_0: gp_Ax2): gp_Ax3 }; + gp_Pln: { new (_0: gp_Ax3): gp_Pln; new (_0: gp_Pnt, _1: gp_Dir): gp_Pln }; gp_Trsf: { new (): gp_Trsf }; - gp_Pln: { new (_0: gp_Ax3): gp_Pln }; TopLoc_Location: { new (_0: gp_Trsf): TopLoc_Location }; + TopoDS: { + vertex(_0: TopoDS_Shape): TopoDS_Vertex; + edge(_0: TopoDS_Shape): TopoDS_Edge; + wire(_0: TopoDS_Shape): TopoDS_Wire; + face(_0: TopoDS_Shape): TopoDS_Face; + shell(_0: TopoDS_Shape): TopoDS_Shell; + solid(_0: TopoDS_Shape): TopoDS_Solid; + compound(_0: TopoDS_Shape): TopoDS_Compound; + compsolid(_0: TopoDS_Shape): TopoDS_CompSolid; + }; TopoDS_Shape: {}; + TColgp_Array1OfPnt: { new (_0: number, _1: number): TColgp_Array1OfPnt }; TopoDS_Vertex: {}; TopoDS_Edge: {}; TopoDS_Wire: {}; @@ -309,24 +784,38 @@ interface EmbindModule { TopoDS_Solid: {}; TopoDS_Compound: {}; TopoDS_CompSolid: {}; - BRep_Tool: { pnt(_0: TopoDS_Vertex): gp_Pnt }; Shape: { sectionSS(_0: TopoDS_Shape, _1: TopoDS_Shape): TopoDS_Shape; sectionSP(_0: TopoDS_Shape, _1: gp_Pln): TopoDS_Shape; isClosed(_0: TopoDS_Shape): boolean; findAncestor(_0: TopoDS_Shape, _1: TopoDS_Shape, _2: TopAbs_ShapeEnum): Array; findSubShapes(_0: TopoDS_Shape, _1: TopAbs_ShapeEnum): Array; + splitByEdgeOrWires(_0: TopoDS_Shape, _1: Array): TopoDS_Shape; }; - EdgeIntersectResult: {}; + Vertex: { point(_0: TopoDS_Vertex): Vector3 }; Edge: { - curve(_0: TopoDS_Edge): Geom_TrimmedCurve; + fromCurve(_0: Geom_Curve | null): TopoDS_Edge; + curve(_0: TopoDS_Edge): Handle_Geom_TrimmedCurve; + curveLength(_0: TopoDS_Edge): number; trim(_0: TopoDS_Edge, _1: number, _2: number): TopoDS_Edge; - intersect(_0: TopoDS_Edge, _1: TopoDS_Edge): EdgeIntersectResult; offset(_0: TopoDS_Edge, _1: gp_Dir, _2: number): TopoDS_Edge; + intersect(_0: TopoDS_Edge, _1: TopoDS_Edge): Array; + }; + Wire: { + offset(_0: TopoDS_Wire, _1: number, _2: GeomAbs_JoinType): TopoDS_Shape; + makeFace(_0: TopoDS_Wire): TopoDS_Face; + }; + Face: { + offset(_0: TopoDS_Face, _1: number, _2: GeomAbs_JoinType): TopoDS_Shape; + outerWire(_0: TopoDS_Face): TopoDS_Wire; + surface(_0: TopoDS_Face): Handle_Geom_Surface; + normal(_0: TopoDS_Face, _1: number, _2: number, _3: gp_Pnt, _4: gp_Vec): void; + curveOnSurface(_0: TopoDS_Face, _1: TopoDS_Edge): Domain; + }; + Transient: { + isKind(_0: Standard_Transient | null, _1: EmbindString): boolean; + isInstance(_0: Standard_Transient | null, _1: EmbindString): boolean; }; - Wire: { offset(_0: TopoDS_Wire, _1: number, _2: GeomAbs_JoinType): TopoDS_Shape }; - Face: { offset(_0: TopoDS_Face, _1: number, _2: GeomAbs_JoinType): TopoDS_Shape }; - ShapeFactory: { makeBox(_0: gp_Ax2, _1: number, _2: number, _3: number): TopoDS_Shape }; } export type MainModule = WasmModule & typeof RuntimeExports & EmbindModule; diff --git a/packages/chili-wasm/lib/chili-wasm.js b/packages/chili-wasm/lib/chili-wasm.js index 06357a9c..07cdd59d 100755 --- a/packages/chili-wasm/lib/chili-wasm.js +++ b/packages/chili-wasm/lib/chili-wasm.js @@ -1,4 +1,4 @@ -var ChiliWasm = (() => { +var Module = (() => { var _scriptName = import.meta.url; return function (moduleArg = {}) { @@ -219,10 +219,10 @@ var ChiliWasm = (() => { var info = getWasmImports(); function receiveInstance(instance, module) { wasmExports = instance.exports; - wasmMemory = wasmExports["fa"]; + wasmMemory = wasmExports["ka"]; updateMemoryViews(); - wasmTable = wasmExports["ka"]; - addOnInit(wasmExports["ga"]); + wasmTable = wasmExports["pa"]; + addOnInit(wasmExports["la"]); removeRunDependency("wasm-instantiate"); return wasmExports; } @@ -260,53 +260,6 @@ var ChiliWasm = (() => { } }; var noExitRuntime = Module["noExitRuntime"] || true; - var UTF8Decoder = typeof TextDecoder != "undefined" ? new TextDecoder() : undefined; - var UTF8ArrayToString = (heapOrArray, idx, maxBytesToRead) => { - var endIdx = idx + maxBytesToRead; - var endPtr = idx; - while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr; - if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) { - return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr)); - } - var str = ""; - while (idx < endPtr) { - var u0 = heapOrArray[idx++]; - if (!(u0 & 128)) { - str += String.fromCharCode(u0); - continue; - } - var u1 = heapOrArray[idx++] & 63; - if ((u0 & 224) == 192) { - str += String.fromCharCode(((u0 & 31) << 6) | u1); - continue; - } - var u2 = heapOrArray[idx++] & 63; - if ((u0 & 240) == 224) { - u0 = ((u0 & 15) << 12) | (u1 << 6) | u2; - } else { - u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63); - } - if (u0 < 65536) { - str += String.fromCharCode(u0); - } else { - var ch = u0 - 65536; - str += String.fromCharCode(55296 | (ch >> 10), 56320 | (ch & 1023)); - } - } - return str; - }; - var UTF8ToString = (ptr, maxBytesToRead) => - ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : ""; - var ___assert_fail = (condition, filename, line, func) => { - abort( - `Assertion failed: ${UTF8ToString(condition)}, at: ` + - [ - filename ? UTF8ToString(filename) : "unknown filename", - line, - func ? UTF8ToString(func) : "unknown function", - ], - ); - }; class ExceptionInfo { constructor(excPtr) { this.excPtr = excPtr; @@ -483,6 +436,41 @@ var ChiliWasm = (() => { return outputParts.join("/"); }, }; + var UTF8Decoder = typeof TextDecoder != "undefined" ? new TextDecoder() : undefined; + var UTF8ArrayToString = (heapOrArray, idx, maxBytesToRead) => { + var endIdx = idx + maxBytesToRead; + var endPtr = idx; + while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr; + if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) { + return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr)); + } + var str = ""; + while (idx < endPtr) { + var u0 = heapOrArray[idx++]; + if (!(u0 & 128)) { + str += String.fromCharCode(u0); + continue; + } + var u1 = heapOrArray[idx++] & 63; + if ((u0 & 224) == 192) { + str += String.fromCharCode(((u0 & 31) << 6) | u1); + continue; + } + var u2 = heapOrArray[idx++] & 63; + if ((u0 & 240) == 224) { + u0 = ((u0 & 15) << 12) | (u1 << 6) | u2; + } else { + u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63); + } + if (u0 < 65536) { + str += String.fromCharCode(u0); + } else { + var ch = u0 - 65536; + str += String.fromCharCode(55296 | (ch >> 10), 56320 | (ch & 1023)); + } + } + return str; + }; var FS_stdin_getChar_buffer = []; var lengthBytesUTF8 = (str) => { var len = 0; @@ -2464,6 +2452,8 @@ var ChiliWasm = (() => { return node; }, }; + var UTF8ToString = (ptr, maxBytesToRead) => + ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : ""; var SYSCALLS = { DEFAULT_POLLMASK: 5, calculateAt(dirfd, path, allowEmpty) { @@ -4301,6 +4291,9 @@ var ChiliWasm = (() => { { ignoreDuplicateRegistrations: true }, ); }; + var __embind_register_optional = (rawOptionalType, rawType) => { + __embind_register_emval(rawOptionalType); + }; var stringToUTF8 = (str, outPtr, maxBytesToWrite) => stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite); var __embind_register_std_string = (rawType, name) => { @@ -4543,6 +4536,28 @@ var ChiliWasm = (() => { fields: [], }; }; + var __embind_register_value_object_field = ( + structType, + fieldName, + getterReturnType, + getterSignature, + getter, + getterContext, + setterArgumentType, + setterSignature, + setter, + setterContext, + ) => { + structRegistrations[structType].fields.push({ + fieldName: readLatin1String(fieldName), + getterReturnType: getterReturnType, + getter: embind__requireFunction(getterSignature, getter), + getterContext: getterContext, + setterArgumentType: setterArgumentType, + setter: embind__requireFunction(setterSignature, setter), + setterContext: setterContext, + }); + }; var __embind_register_void = (rawType, name) => { name = readLatin1String(name); registerType(rawType, { @@ -4655,6 +4670,19 @@ var ChiliWasm = (() => { noExitRuntime = false; runtimeKeepaliveCounter = 0; }; + var emval_returnValue = (returnType, destructorsRef, handle) => { + var destructors = []; + var result = returnType["toWireType"](destructors, handle); + if (destructors.length) { + HEAPU32[destructorsRef >> 2] = Emval.toHandle(destructors); + } + return result; + }; + var __emval_as = (handle, returnType, destructorsRef) => { + handle = Emval.toValue(handle); + returnType = requireRegisteredType(returnType, "emval::as"); + return emval_returnValue(returnType, destructorsRef, handle); + }; var emval_symbols = {}; var getStringOrSymbol = (address) => { var symbol = emval_symbols[address]; @@ -4683,14 +4711,6 @@ var ChiliWasm = (() => { return a; }; var reflectConstruct = Reflect.construct; - var emval_returnValue = (returnType, destructorsRef, handle) => { - var destructors = []; - var result = returnType["toWireType"](destructors, handle); - if (destructors.length) { - HEAPU32[destructorsRef >> 2] = Emval.toHandle(destructors); - } - return result; - }; var __emval_get_method_caller = (argCount, argTypes, kind) => { var types = emval_lookupTypes(argCount, argTypes); var retType = types.shift(); @@ -4723,12 +4743,24 @@ var ChiliWasm = (() => { var functionName = `methodCaller<(${types.map((t) => t.name).join(", ")}) => ${retType.name}>`; return emval_addMethodCaller(createNamedFunction(functionName, invokerFunction)); }; + var __emval_get_property = (handle, key) => { + handle = Emval.toValue(handle); + key = Emval.toValue(key); + return Emval.toHandle(handle[key]); + }; var __emval_incref = (handle) => { if (handle > 9) { emval_handles[handle + 1] += 1; } }; var __emval_new_array = () => Emval.toHandle([]); + var __emval_new_array_from_memory_view = (view) => { + view = Emval.toValue(view); + var a = new Array(view.length); + for (var i = 0; i < view.length; i++) a[i] = view[i]; + return Emval.toHandle(a); + }; + var __emval_new_cstring = (v) => Emval.toHandle(getStringOrSymbol(v)); var __emval_run_destructors = (handle) => { var destructors = Emval.toValue(handle); runDestructors(destructors); @@ -5716,81 +5748,86 @@ var ChiliWasm = (() => { var preloadedImages = {}; var preloadedAudios = {}; var wasmImports = { - _: OSD_MemInfo_getModuleHeapLength, - n: ___assert_fail, + ha: OSD_MemInfo_getModuleHeapLength, a: ___cxa_throw, - V: ___syscall_chmod, - W: ___syscall_faccessat, - t: ___syscall_fcntl64, - R: ___syscall_fstat64, - Y: ___syscall_ioctl, - P: ___syscall_lstat64, - L: ___syscall_mkdirat, - O: ___syscall_newfstatat, - w: ___syscall_openat, - Q: ___syscall_stat64, - K: __abort_js, - aa: __embind_finalize_value_object, - D: __embind_register_bigint, - da: __embind_register_bool, + ba: ___syscall_chmod, + ca: ___syscall_faccessat, + C: ___syscall_fcntl64, + Z: ___syscall_fstat64, + fa: ___syscall_ioctl, + X: ___syscall_lstat64, + T: ___syscall_mkdirat, + W: ___syscall_newfstatat, + F: ___syscall_openat, + Y: ___syscall_stat64, + S: __abort_js, + o: __embind_finalize_value_object, + L: __embind_register_bigint, + ea: __embind_register_bool, c: __embind_register_class, - j: __embind_register_class_class_function, - k: __embind_register_class_constructor, + d: __embind_register_class_class_function, + i: __embind_register_class_constructor, b: __embind_register_class_function, - d: __embind_register_class_property, - ca: __embind_register_emval, - u: __embind_register_enum, - i: __embind_register_enum_value, - z: __embind_register_float, - l: __embind_register_integer, - e: __embind_register_memory_view, - A: __embind_register_std_string, - v: __embind_register_std_wstring, - h: __embind_register_user_type, - ba: __embind_register_value_object, - ea: __embind_register_void, - T: __emscripten_get_now_is_monotonic, - F: __emscripten_lookup_name, - S: __emscripten_memcpy_js, - J: __emscripten_runtime_keepalive_clear, - q: __emval_call_method, - f: __emval_decref, - p: __emval_get_method_caller, - g: __emval_incref, - m: __emval_new_array, - r: __emval_run_destructors, - o: __emval_take_value, - B: __localtime_js, - E: __setitimer_js, - X: __tzset_js, - U: _emscripten_date_now, - H: _emscripten_get_heap_max, - $: _emscripten_get_preloaded_image_data, - G: _emscripten_resize_heap, - M: _environ_get, - N: _environ_sizes_get, - Z: _exit, - s: _fd_close, - y: _fd_read, - C: _fd_seek, - x: _fd_write, - I: _proc_exit, + g: __embind_register_class_property, + I: __embind_register_emval, + y: __embind_register_enum, + h: __embind_register_enum_value, + D: __embind_register_float, + s: __embind_register_integer, + k: __embind_register_memory_view, + z: __embind_register_optional, + E: __embind_register_std_string, + A: __embind_register_std_wstring, + l: __embind_register_user_type, + p: __embind_register_value_object, + f: __embind_register_value_object_field, + ja: __embind_register_void, + $: __emscripten_get_now_is_monotonic, + N: __emscripten_lookup_name, + _: __emscripten_memcpy_js, + R: __emscripten_runtime_keepalive_clear, + q: __emval_as, + u: __emval_call_method, + e: __emval_decref, + t: __emval_get_method_caller, + r: __emval_get_property, + j: __emval_incref, + v: __emval_new_array, + w: __emval_new_array_from_memory_view, + x: __emval_new_cstring, + m: __emval_run_destructors, + n: __emval_take_value, + J: __localtime_js, + M: __setitimer_js, + da: __tzset_js, + aa: _emscripten_date_now, + P: _emscripten_get_heap_max, + ia: _emscripten_get_preloaded_image_data, + O: _emscripten_resize_heap, + U: _environ_get, + V: _environ_sizes_get, + ga: _exit, + B: _fd_close, + H: _fd_read, + K: _fd_seek, + G: _fd_write, + Q: _proc_exit, }; var wasmExports = createWasm(); - var ___wasm_call_ctors = () => (___wasm_call_ctors = wasmExports["ga"])(); - var ___getTypeName = (a0) => (___getTypeName = wasmExports["ha"])(a0); - var _free = (a0) => (_free = wasmExports["ia"])(a0); - var _malloc = (a0) => (_malloc = wasmExports["ja"])(a0); - var _htons = (a0) => (_htons = wasmExports["la"])(a0); + var ___wasm_call_ctors = () => (___wasm_call_ctors = wasmExports["la"])(); + var ___getTypeName = (a0) => (___getTypeName = wasmExports["ma"])(a0); + var _malloc = (a0) => (_malloc = wasmExports["na"])(a0); + var _free = (a0) => (_free = wasmExports["oa"])(a0); + var _htons = (a0) => (_htons = wasmExports["qa"])(a0); var _emscripten_builtin_memalign = (a0, a1) => - (_emscripten_builtin_memalign = wasmExports["ma"])(a0, a1); - var __emscripten_timeout = (a0, a1) => (__emscripten_timeout = wasmExports["na"])(a0, a1); + (_emscripten_builtin_memalign = wasmExports["ra"])(a0, a1); + var __emscripten_timeout = (a0, a1) => (__emscripten_timeout = wasmExports["sa"])(a0, a1); var dynCall_jiji = (Module["dynCall_jiji"] = (a0, a1, a2, a3, a4) => - (dynCall_jiji = Module["dynCall_jiji"] = wasmExports["oa"])(a0, a1, a2, a3, a4)); + (dynCall_jiji = Module["dynCall_jiji"] = wasmExports["ta"])(a0, a1, a2, a3, a4)); var dynCall_viiijj = (Module["dynCall_viiijj"] = (a0, a1, a2, a3, a4, a5, a6, a7) => - (dynCall_viiijj = Module["dynCall_viiijj"] = wasmExports["pa"])(a0, a1, a2, a3, a4, a5, a6, a7)); + (dynCall_viiijj = Module["dynCall_viiijj"] = wasmExports["ua"])(a0, a1, a2, a3, a4, a5, a6, a7)); var dynCall_viiiiji = (Module["dynCall_viiiiji"] = (a0, a1, a2, a3, a4, a5, a6, a7) => - (dynCall_viiiiji = Module["dynCall_viiiiji"] = wasmExports["qa"])( + (dynCall_viiiiji = Module["dynCall_viiiiji"] = wasmExports["va"])( a0, a1, a2, @@ -5801,11 +5838,11 @@ var ChiliWasm = (() => { a7, )); var dynCall_viijii = (Module["dynCall_viijii"] = (a0, a1, a2, a3, a4, a5, a6) => - (dynCall_viijii = Module["dynCall_viijii"] = wasmExports["ra"])(a0, a1, a2, a3, a4, a5, a6)); + (dynCall_viijii = Module["dynCall_viijii"] = wasmExports["wa"])(a0, a1, a2, a3, a4, a5, a6)); var dynCall_iiiiij = (Module["dynCall_iiiiij"] = (a0, a1, a2, a3, a4, a5, a6) => - (dynCall_iiiiij = Module["dynCall_iiiiij"] = wasmExports["sa"])(a0, a1, a2, a3, a4, a5, a6)); + (dynCall_iiiiij = Module["dynCall_iiiiij"] = wasmExports["xa"])(a0, a1, a2, a3, a4, a5, a6)); var dynCall_iiiiijj = (Module["dynCall_iiiiijj"] = (a0, a1, a2, a3, a4, a5, a6, a7, a8) => - (dynCall_iiiiijj = Module["dynCall_iiiiijj"] = wasmExports["ta"])( + (dynCall_iiiiijj = Module["dynCall_iiiiijj"] = wasmExports["ya"])( a0, a1, a2, @@ -5817,7 +5854,7 @@ var ChiliWasm = (() => { a8, )); var dynCall_iiiiiijj = (Module["dynCall_iiiiiijj"] = (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) => - (dynCall_iiiiiijj = Module["dynCall_iiiiiijj"] = wasmExports["ua"])( + (dynCall_iiiiiijj = Module["dynCall_iiiiiijj"] = wasmExports["za"])( a0, a1, a2, @@ -5876,4 +5913,4 @@ var ChiliWasm = (() => { return moduleRtn; }; })(); -export default ChiliWasm; +export default Module; diff --git a/packages/chili-wasm/lib/chili-wasm.wasm b/packages/chili-wasm/lib/chili-wasm.wasm index e5ed654d..aa158b98 100644 Binary files a/packages/chili-wasm/lib/chili-wasm.wasm and b/packages/chili-wasm/lib/chili-wasm.wasm differ diff --git a/packages/chili-wasm/src/converter.ts b/packages/chili-wasm/src/converter.ts new file mode 100644 index 00000000..2bac35de --- /dev/null +++ b/packages/chili-wasm/src/converter.ts @@ -0,0 +1,28 @@ +import { IShape, IShapeConverter, Result } from "chili-core"; +import { OccShape } from "./shape"; +import { OcctHelper } from "./helper"; + +export class OccShapeConverter implements IShapeConverter { + convertToIGES(...shapes: IShape[]): Result { + throw new Error("Method not implemented."); + } + convertFromIGES(iges: string): Result { + throw new Error("Method not implemented."); + } + convertToSTEP(...shapes: IShape[]): Result { + throw new Error("Method not implemented."); + } + convertFromSTEP(step: string): Result { + throw new Error("Method not implemented."); + } + convertToBrep(shape: IShape): Result { + if (shape instanceof OccShape) { + return Result.ok(wasm.Converter.convertToBrep(shape.shape)); + } + return Result.err("Shape is not an OccShape"); + } + convertFromBrep(brep: string): Result { + let shape = wasm.Converter.convertFromBrep(brep); + return Result.ok(OcctHelper.wrapShape(shape)); + } +} diff --git a/packages/chili-wasm/src/curve.ts b/packages/chili-wasm/src/curve.ts new file mode 100644 index 00000000..599e381d --- /dev/null +++ b/packages/chili-wasm/src/curve.ts @@ -0,0 +1,554 @@ +// Copyright 2022-2023 the Chili authors. All rights reserved. AGPL-3.0 license. + +import { + Continuity, + CurveType, + IBSplineCurve, + IBezierCurve, + IBoundedCurve, + ICircle, + IConic, + ICurve, + IDisposable, + IEdge, + IEllipse, + IGeometry, + IHyperbola, + ILine, + IOffsetCurve, + IParabola, + ITrimmedCurve, + Ray, + XYZ, + gc, +} from "chili-core"; +import { + Geom_BSplineCurve, + Geom_BezierCurve, + Geom_BoundedCurve, + Geom_Circle, + Geom_Conic, + Geom_Curve, + Geom_Ellipse, + Geom_Hyperbola, + Geom_Line, + Geom_OffsetCurve, + Geom_Parabola, + Geom_TrimmedCurve, +} from "../lib/chili-wasm"; +import { OccGeometry } from "./geometry"; +import { OcctHelper } from "./helper"; +import { OccEdge } from "./shape"; + +export class OccCurve extends OccGeometry implements ICurve, IDisposable { + readonly curveType: CurveType; + + constructor(readonly curve: Geom_Curve) { + super(curve); + this.curveType = OcctHelper.getCurveType(curve); + } + + override copy(): IGeometry { + return gc((c) => { + let newCurve = c(this.curve.copy()); + return OcctHelper.wrapCurve(newCurve.get() as Geom_Curve); + }); + } + + makeEdge(): IEdge { + return new OccEdge(wasm.Edge.fromCurve(this.curve)); + } + + nearestExtrema(curve: ICurve | Ray) { + return gc((c) => { + let result: any; + if (curve instanceof OccCurve) { + result = wasm.Curve.nearestExtremaCC(this.curve, curve.curve); + } + if (curve instanceof Ray) { + let line = c(wasm.Curve.makeLine(curve.location, curve.direction)); + result = wasm.Curve.nearestExtremaCC(this.curve, line.get()); + } + return result; + }); + } + + uniformAbscissaByLength(length: number): XYZ[] { + return wasm.Curve.uniformAbscissaWithLength(this.curve, length).map((x) => OcctHelper.toXYZ(x)); + } + + uniformAbscissaByCount(curveCount: number): XYZ[] { + return wasm.Curve.uniformAbscissaWithCount(this.curve, curveCount + 1).map((x) => + OcctHelper.toXYZ(x), + ); + } + + length(): number { + return wasm.Curve.curveLength(this.curve); + } + + trim(u1: number, u2: number): ITrimmedCurve { + return gc((c) => { + let trimCurve = c(wasm.Curve.trim(this.curve, u1, u2)); + return new OccTrimmedCurve(trimCurve.get()!); + }); + } + + reverse() { + this.curve.reverse(); + } + + reversed(): ICurve { + return gc((c) => { + let newCurve = c(this.curve.reversed()); + return OcctHelper.wrapCurve(newCurve.get()!); + }); + } + + isClosed(): boolean { + return this.curve.isClosed(); + } + + period(): number { + return this.curve.period(); + } + + isPeriodic(): boolean { + return this.curve.isPeriodic(); + } + + continutity(): Continuity { + let cni = this.curve.continutity(); + return OcctHelper.convertContinuity(cni); + } + + nearestFromPoint(point: XYZ) { + let res = wasm.Curve.projectOrNearest(this.curve, point); + return { + ...res, + point: OcctHelper.toXYZ(res.point), + }; + } + + value(parameter: number): XYZ { + return OcctHelper.toXYZ(this.curve.value(parameter)); + } + + firstParameter() { + return this.curve.firstParameter(); + } + + lastParameter() { + return this.curve.lastParameter(); + } + + parameter(point: XYZ, tolerance: number): number | undefined { + return wasm.Curve.parameter(this.curve, point, tolerance); + } + + project(point: XYZ): XYZ[] { + return wasm.Curve.projects(this.curve, point) + .map((p) => new XYZ(p.x, p.y, p.z)) + .toSorted((a, b) => a.distanceTo(point) - b.distanceTo(point)); + } + + isCN(n: number): boolean { + return this.curve.isCN(n); + } + + d0(u: number) { + return gc((c) => { + let pnt = c(new wasm.gp_Pnt(0, 0, 0)); + this.curve.d0(u, pnt); + return OcctHelper.toXYZ(pnt); + }); + } + + d1(u: number) { + return gc((c) => { + let pnt = c(new wasm.gp_Pnt(0, 0, 0)); + let vec = c(new wasm.gp_Vec(0, 0, 0)); + this.curve.d1(u, pnt, vec); + return { + point: OcctHelper.toXYZ(pnt), + vec: OcctHelper.toXYZ(vec), + }; + }); + } + + d2(u: number) { + return gc((c) => { + let pnt = c(new wasm.gp_Pnt(0, 0, 0)); + let vec1 = c(new wasm.gp_Vec(0, 0, 0)); + let vec2 = c(new wasm.gp_Vec(0, 0, 0)); + this.curve.d2(u, pnt, vec1, vec2); + return { + point: OcctHelper.toXYZ(pnt), + vec1: OcctHelper.toXYZ(vec1), + vec2: OcctHelper.toXYZ(vec2), + }; + }); + } + + d3(u: number) { + return gc((c) => { + let pnt = c(new wasm.gp_Pnt(0, 0, 0)); + let vec1 = c(new wasm.gp_Vec(0, 0, 0)); + let vec2 = c(new wasm.gp_Vec(0, 0, 0)); + let vec3 = c(new wasm.gp_Vec(0, 0, 0)); + this.curve.d3(u, pnt, vec1, vec2, vec3); + return { + point: OcctHelper.toXYZ(pnt), + vec1: OcctHelper.toXYZ(vec1), + vec2: OcctHelper.toXYZ(vec2), + vec3: OcctHelper.toXYZ(vec3), + }; + }); + } + + dn(u: number, n: number) { + return gc((c) => { + return OcctHelper.toXYZ(c(this.curve.dn(u, n))); + }); + } +} + +export class OccLine extends OccCurve implements ILine { + constructor(private line: Geom_Line) { + super(line); + } + + get direction(): XYZ { + return gc((c) => { + let ax = c(this.line.position()); + return OcctHelper.toXYZ(c(ax.direction)); + }); + } + + set direction(value: XYZ) { + gc((c) => { + this.line.setDirection(c(OcctHelper.toDir(value))); + }); + } + + get location(): XYZ { + return gc((c) => { + let ax = c(this.line.position()); + return OcctHelper.toXYZ(c(ax.location)); + }); + } + + set location(value: XYZ) { + gc((c) => { + this.line.setLocation(c(OcctHelper.toPnt(value))); + }); + } +} + +export class OccConic extends OccCurve implements IConic { + constructor(private conioc: Geom_Conic) { + super(conioc); + } + get axis(): XYZ { + return gc((c) => { + return OcctHelper.toXYZ(c(c(this.conioc.axis()).direction)); + }); + } + get xAxis(): XYZ { + return gc((c) => { + return OcctHelper.toXYZ(c(c(this.conioc.xAxis()).direction)); + }); + } + get yAxis(): XYZ { + return gc((c) => { + return OcctHelper.toXYZ(c(c(this.conioc.yAxis()).direction)); + }); + } + eccentricity(): number { + return this.conioc.eccentricity(); + } +} + +export class OccCircle extends OccConic implements ICircle { + constructor(private circle: Geom_Circle) { + super(circle); + } + + get center(): XYZ { + return gc((c) => { + return OcctHelper.toXYZ(c(this.circle.location())); + }); + } + + set center(value: XYZ) { + gc((c) => { + this.circle.setLocation(c(OcctHelper.toPnt(value))); + }); + } + + get radius(): number { + return this.circle.radius(); + } + + set radius(value: number) { + this.circle.setRadius(value); + } +} + +export class OccEllipse extends OccConic implements IEllipse { + constructor(private ellipse: Geom_Ellipse) { + super(ellipse); + } + + get center(): XYZ { + return gc((c) => { + return OcctHelper.toXYZ(c(this.ellipse.location())); + }); + } + set center(value: XYZ) { + gc((c) => { + this.ellipse.setLocation(c(OcctHelper.toPnt(value))); + }); + } + + get focus1(): XYZ { + return gc((c) => OcctHelper.toXYZ(c(this.ellipse.focus1()))); + } + get focus2(): XYZ { + return gc((c) => OcctHelper.toXYZ(c(this.ellipse.focus2()))); + } + + get majorRadius(): number { + return this.ellipse.majorRadius(); + } + set majorRadius(value: number) { + this.ellipse.setMajorRadius(value); + } + + get minorRadius(): number { + return this.ellipse.minorRadius(); + } + set minorRadius(value: number) { + this.ellipse.setMinorRadius(value); + } +} + +export class OccHyperbola extends OccConic implements IHyperbola { + constructor(private hyperbola: Geom_Hyperbola) { + super(hyperbola); + } + focal(): number { + return this.hyperbola.focal(); + } + get location(): XYZ { + return gc((c) => { + return OcctHelper.toXYZ(c(this.hyperbola.location())); + }); + } + set location(value: XYZ) { + gc((c) => { + this.hyperbola.setLocation(c(OcctHelper.toPnt(value))); + }); + } + + get focus1(): XYZ { + return gc((c) => OcctHelper.toXYZ(c(this.hyperbola.focus1()))); + } + get focus2(): XYZ { + return gc((c) => OcctHelper.toXYZ(c(this.hyperbola.focus2()))); + } + get majorRadius(): number { + return this.hyperbola.majorRadius(); + } + set majorRadius(value: number) { + this.hyperbola.setMajorRadius(value); + } + + get minorRadius(): number { + return this.hyperbola.minorRadius(); + } + set minorRadius(value: number) { + this.hyperbola.setMinorRadius(value); + } +} + +export class OccParabola extends OccConic implements IParabola { + constructor(private parabola: Geom_Parabola) { + super(parabola); + } + focal(): number { + return this.parabola.focal(); + } + + get focus(): XYZ { + return gc((c) => OcctHelper.toXYZ(c(this.parabola.focus()))); + } + + get directrix() { + return gc((c) => OcctHelper.toXYZ(c(c(this.parabola.directrix().location)))); + } +} + +export class OccBoundedCurve extends OccCurve implements IBoundedCurve { + constructor(private boundedCurve: Geom_BoundedCurve) { + super(boundedCurve); + } + + startPoint(): XYZ { + return gc((c) => OcctHelper.toXYZ(c(this.boundedCurve.startPoint()))); + } + + endPoint(): XYZ { + return gc((c) => OcctHelper.toXYZ(c(this.boundedCurve.endPoint()))); + } +} + +export class OccTrimmedCurve extends OccBoundedCurve implements ITrimmedCurve { + constructor(private trimmedCurve: Geom_TrimmedCurve) { + super(trimmedCurve); + } + + setTrim(u1: number, u2: number): void { + this.trimmedCurve.setTrim(u1, u2, true, true); + } + + basisCurve(): ICurve { + return gc((c) => { + let curve = c(this.trimmedCurve.basisCurve()); + return OcctHelper.wrapCurve(curve.get()!); + }); + } +} + +export class OccOffsetCurve extends OccCurve implements IOffsetCurve { + constructor(private offsetCurve: Geom_OffsetCurve) { + super(offsetCurve); + } + + basisCurve(): ICurve { + return gc((c) => { + let curve = c(this.offsetCurve.basisCurve()); + return OcctHelper.wrapCurve(curve.get()!); + }); + } + + offset(): number { + return this.offsetCurve.offset(); + } + + direction(): XYZ { + return gc((c) => OcctHelper.toXYZ(c(this.offsetCurve.direction()))); + } +} + +export class OccBezierCurve extends OccBoundedCurve implements IBezierCurve { + constructor(private bezier: Geom_BezierCurve) { + super(bezier); + } + + weight(index: number): number { + return this.bezier.weight(index); + } + + insertPoleAfter(index: number, point: XYZ, weight: number | undefined): void { + gc((c) => { + if (weight === undefined) { + this.bezier.insertPoleAfter(index, c(OcctHelper.toPnt(point))); + } else { + this.bezier.insertPoleAfterWithWeight(index, c(OcctHelper.toPnt(point)), weight); + } + }); + } + + insertPoleBefore(index: number, point: XYZ, weight: number | undefined): void { + gc((c) => { + if (weight === undefined) { + this.bezier.insertPoleBefore(index, c(OcctHelper.toPnt(point))); + } else { + this.bezier.insertPoleBeforeWithWeight(index, c(OcctHelper.toPnt(point)), weight); + } + }); + } + + removePole(index: number): void { + this.bezier.removePole(index); + } + + setPole(index: number, point: XYZ, weight: number | undefined): void { + gc((c) => { + if (weight === undefined) { + this.bezier.setPole(index, c(OcctHelper.toPnt(point))); + } else { + this.bezier.setPoleWithWeight(index, c(OcctHelper.toPnt(point)), weight); + } + }); + } + + setWeight(index: number, weight: number): void { + this.setWeight(index, weight); + } + + nbPoles(): number { + return this.bezier.nbPoles(); + } + + pole(index: number): XYZ { + return gc((c) => OcctHelper.toXYZ(c(this.bezier.pole(index)))); + } + + degree(): number { + return this.bezier.degree(); + } + + poles(): XYZ[] { + return gc((c) => { + let result: XYZ[] = []; + let pls = c(this.bezier.getPoles()); + for (let i = 1; i <= pls.length(); i++) { + result.push(OcctHelper.toXYZ(c(pls.value(i)))); + } + return result; + }); + } +} + +export class OccBSplineCurve extends OccBoundedCurve implements IBSplineCurve { + constructor(private bspline: Geom_BSplineCurve) { + super(bspline); + } + nbKnots(): number { + return this.bspline.nbKnots(); + } + knot(index: number): number { + return this.bspline.knot(index); + } + setKnot(index: number, value: number): void { + this.bspline.setKnot(index, value); + } + nbPoles(): number { + return this.bspline.nbPoles(); + } + pole(index: number): XYZ { + return gc((c) => OcctHelper.toXYZ(c(this.bspline.pole(index)))); + } + poles(): XYZ[] { + return gc((c) => { + let result: XYZ[] = []; + let pls = c(this.bspline.getPoles()); + for (let i = 1; i <= pls.length(); i++) { + result.push(OcctHelper.toXYZ(c(pls.value(i)))); + } + return result; + }); + } + weight(index: number): number { + return this.bspline.weight(index); + } + setWeight(index: number, value: number): void { + this.bspline.setWeight(index, value); + } + + degree(): number { + return this.bspline.degree(); + } +} diff --git a/packages/chili-wasm/src/factory.ts b/packages/chili-wasm/src/factory.ts new file mode 100644 index 00000000..905c4e5c --- /dev/null +++ b/packages/chili-wasm/src/factory.ts @@ -0,0 +1,136 @@ +import { + ICompound, + IEdge, + IFace, + IShape, + IShapeConverter, + IShapeFactory, + ISolid, + IVertex, + IWire, + MathUtils, + Plane, + Ray, + Result, + XYZ, + gc, +} from "chili-core"; +import { OccShapeConverter } from "./converter"; +import { ShapeResult, TopoDS_Shape } from "../lib/chili-wasm"; +import { OccShape } from "./shape"; +import { OcctHelper } from "./helper"; + +function ensureOccShape(...shapes: IShape[]): TopoDS_Shape[] { + return shapes.map((x) => { + if (!(x instanceof OccShape)) { + throw new Error("The OCC kernel only supports OCC geometries."); + } + return x.shape; + }); +} + +function convertShapeResult(result: ShapeResult): Result { + return gc((c) => { + // c(result); + if (!result.isOk) { + return Result.err(String(result.error)); + } + return Result.ok(OcctHelper.wrapShape(result.shape)); + }); +} + +export class ShapeFactory implements IShapeFactory { + readonly converter: IShapeConverter; + constructor() { + this.converter = new OccShapeConverter(); + } + + face(...wire: IWire[]): Result { + let shapes = ensureOccShape(...wire); + return convertShapeResult(wasm.ShapeFactory.face(shapes)) as Result; + } + bezier(points: XYZ[], weights?: number[]): Result { + return convertShapeResult(wasm.ShapeFactory.bezier(points, weights ?? [])) as Result; + } + point(point: XYZ): Result { + return convertShapeResult(wasm.ShapeFactory.point(point)) as Result; + } + line(start: XYZ, end: XYZ): Result { + return convertShapeResult(wasm.ShapeFactory.line(start, end)) as Result; + } + arc(normal: XYZ, center: XYZ, start: XYZ, angle: number): Result { + return convertShapeResult( + wasm.ShapeFactory.arc(normal, center, start, MathUtils.degToRad(angle)), + ) as Result; + } + circle(normal: XYZ, center: XYZ, radius: number): Result { + return convertShapeResult(wasm.ShapeFactory.circle(normal, center, radius)) as Result; + } + rect(plane: Plane, dx: number, dy: number): Result { + return convertShapeResult(wasm.ShapeFactory.rect(OcctHelper.toAx3(plane), dx, dy)) as Result; + } + polygon(...points: XYZ[]): Result { + return convertShapeResult(wasm.ShapeFactory.polygon(points)) as Result; + } + box(plane: Plane, dx: number, dy: number, dz: number): Result { + return convertShapeResult( + wasm.ShapeFactory.box(OcctHelper.toAx3(plane), dx, dy, dz), + ) as Result; + } + wire(...edges: IEdge[]): Result { + return convertShapeResult(wasm.ShapeFactory.wire(ensureOccShape(...edges))) as Result; + } + prism(shape: IShape, vec: XYZ): Result { + if (vec.length() === 0) { + return Result.err(`The vector length is 0, the prism cannot be created.`); + } + return convertShapeResult(wasm.ShapeFactory.prism(ensureOccShape(shape)[0], vec)); + } + fuse(bottom: IShape, top: IShape): Result { + return convertShapeResult( + wasm.ShapeFactory.booleanFuse(ensureOccShape(bottom), ensureOccShape(top)), + ); + } + sweep(profile: IShape, path: IWire): Result { + return convertShapeResult( + wasm.ShapeFactory.sweep(ensureOccShape(profile)[0], ensureOccShape(path)[0]), + ); + } + revolve(profile: IShape, axis: Ray, angle: number): Result { + return convertShapeResult( + wasm.ShapeFactory.revolve(ensureOccShape(profile)[0], axis, MathUtils.degToRad(angle)), + ); + } + booleanCommon(shape1: IShape, shape2: IShape): Result { + return convertShapeResult( + wasm.ShapeFactory.booleanCommon(ensureOccShape(shape1), ensureOccShape(shape2)), + ); + } + booleanCut(shape1: IShape, shape2: IShape): Result { + return convertShapeResult( + wasm.ShapeFactory.booleanCut(ensureOccShape(shape1), ensureOccShape(shape2)), + ); + } + booleanFuse(shape1: IShape, shape2: IShape): Result { + return convertShapeResult( + wasm.ShapeFactory.booleanFuse(ensureOccShape(shape1), ensureOccShape(shape2)), + ); + } + combine(...shapes: IShape[]): Result { + return convertShapeResult(wasm.ShapeFactory.combine(ensureOccShape(...shapes))) as Result; + } + makeThickSolidBySimple(shape: IShape, thickness: number): Result { + return convertShapeResult( + wasm.ShapeFactory.makeThickSolidBySimple(ensureOccShape(shape)[0], thickness), + ); + } + makeThickSolidByJoin(shape: IShape, closingFaces: IShape[], thickness: number): Result { + return convertShapeResult( + wasm.ShapeFactory.makeThickSolidByJoin( + ensureOccShape(shape)[0], + ensureOccShape(...closingFaces), + thickness, + ), + ); + } +} diff --git a/packages/chili-wasm/src/geometry.ts b/packages/chili-wasm/src/geometry.ts new file mode 100644 index 00000000..91030999 --- /dev/null +++ b/packages/chili-wasm/src/geometry.ts @@ -0,0 +1,36 @@ +// Copyright 2022-2023 the Chili authors. All rights reserved. AGPL-3.0 license. + +import { GeometryType, IGeometry } from "chili-core"; +import { Geom_Geometry, Handle_Geom_Geometry } from "../lib/chili-wasm"; + +export abstract class OccGeometry implements IGeometry { + private readonly _geometryType: GeometryType; + private readonly _handleGeometry: Handle_Geom_Geometry; + + get geometryType(): GeometryType { + return this._geometryType; + } + + constructor(readonly geometry: Geom_Geometry) { + this._handleGeometry = new wasm.Handle_Geom_Geometry(geometry); + this._geometryType = this.getGeometryType(geometry); + } + + private getGeometryType(geometry: Geom_Geometry) { + let isKind = (type: string) => wasm.Transient.isKind(geometry, type); + + if (isKind("Geom_Curve")) { + return GeometryType.Curve; + } else if (isKind("Geom_Surface")) { + return GeometryType.Surface; + } + + throw new Error("Unknown geometry type"); + } + + dispose() { + this._handleGeometry.delete(); + } + + abstract copy(): IGeometry; +} diff --git a/packages/chili-wasm/src/helper.ts b/packages/chili-wasm/src/helper.ts index 8bfb2094..d3e90fab 100644 --- a/packages/chili-wasm/src/helper.ts +++ b/packages/chili-wasm/src/helper.ts @@ -1,8 +1,185 @@ -import { IShape, Orientation, ShapeType } from "chili-core"; -import { TopAbs_ShapeEnum, TopoDS_Shape } from "../lib/chili-wasm"; -import { OccShape } from "./shape"; +import { + Continuity, + CurveType, + gc, + ICurve, + Id, + IShape, + ISurface, + JoinType, + Matrix4, + Orientation, + Plane, + ShapeType, + SurfaceType, + XYZ, +} from "chili-core"; +import { + Geom_BezierCurve, + Geom_BSplineCurve, + Geom_Circle, + Geom_Curve, + Geom_Ellipse, + Geom_Hyperbola, + Geom_Line, + Geom_OffsetCurve, + Geom_Parabola, + Geom_Surface, + Geom_TrimmedCurve, + GeomAbs_JoinType, + GeomAbs_Shape, + gp_Ax2, + gp_Ax3, + gp_Dir, + gp_Pln, + gp_Pnt, + gp_Trsf, + gp_Vec, + TopAbs_ShapeEnum, + TopoDS_Shape, + Vector3, +} from "../lib/chili-wasm"; +import { + OccCompound, + OccCompSolid, + OccEdge, + OccFace, + OccShape, + OccShell, + OccSolid, + OccVertex, + OccWire, +} from "./shape"; +import { + OccBezierCurve, + OccBSplineCurve, + OccCircle, + OccCurve, + OccEllipse, + OccHyperbola, + OccLine, + OccOffsetCurve, + OccParabola, + OccTrimmedCurve, +} from "./curve"; +import { + OccBezierSurface, + OccBSplineSurface, + OccCompositeSurface, + OccConicalSurface, + OccCylindricalSurface, + OccOffsetSurface, + OccPlane, + OccPlateSurface, + OccRectangularSurface, + OccSphericalSurface, + OccSurfaceOfLinearExtrusion, + OccSurfaceOfRevolution, + OccToroidalSurface, +} from "./surface"; export class OcctHelper { + static toXYZ(p: gp_Pnt | gp_Dir | gp_Vec | Vector3): XYZ { + return new XYZ(p.x, p.y, p.z); + } + + static toDir(value: Vector3) { + return new wasm.gp_Dir(value.x, value.y, value.z); + } + + static toPnt(value: Vector3) { + return new wasm.gp_Pnt(value.x, value.y, value.z); + } + + static toVec(value: Vector3) { + return new wasm.gp_Vec(value.x, value.y, value.z); + } + + static toAx2(plane: Plane): gp_Ax2 { + return gc((c) => { + return new wasm.gp_Ax2( + c(OcctHelper.toPnt(plane.origin)), + c(OcctHelper.toDir(plane.normal)), + c(OcctHelper.toDir(plane.xvec)), + ); + }); + } + + static toAx3(plane: Plane): gp_Ax3 { + return gc((c) => { + return new wasm.gp_Ax3( + c(OcctHelper.toPnt(plane.origin)), + c(OcctHelper.toDir(plane.normal)), + c(OcctHelper.toDir(plane.xvec)), + ); + }); + } + + static fromAx23(ax: gp_Ax2 | gp_Ax3): Plane { + return gc((c) => { + return new Plane( + OcctHelper.toXYZ(c(ax.location)), + OcctHelper.toXYZ(c(ax.direction)), + OcctHelper.toXYZ(c(ax.xDirection)), + ); + }); + } + + static fromPln(pln: gp_Pln): Plane { + return gc((c) => { + let ax3 = c(pln.position); + return this.fromAx23(ax3); + }); + } + + static toPln(plane: Plane): gp_Pln { + return gc((c) => { + return new wasm.gp_Pln(c(OcctHelper.toAx3(plane))); + }); + } + + static convertFromMatrix(matrix: Matrix4): gp_Trsf { + const arr = matrix.toArray(); + let trsf = new wasm.gp_Trsf(); + trsf.setValues( + arr[0], + arr[4], + arr[8], + arr[12], + arr[1], + arr[5], + arr[9], + arr[13], + arr[2], + arr[6], + arr[10], + arr[14], + ); + return trsf; + } + + static convertToMatrix(matrix: gp_Trsf): Matrix4 { + const arr: number[] = [ + matrix.value(1, 1), + matrix.value(2, 1), + matrix.value(3, 1), + 0, + matrix.value(1, 2), + matrix.value(2, 2), + matrix.value(3, 2), + 0, + matrix.value(1, 3), + matrix.value(2, 3), + matrix.value(3, 3), + 0, + matrix.value(1, 4), + matrix.value(2, 4), + matrix.value(3, 4), + 1, + ]; + return Matrix4.fromArray(arr); + } + static getOrientation(shape: TopoDS_Shape): Orientation { switch (shape.orientation()) { case wasm.TopAbs_Orientation.TopAbs_FORWARD: @@ -66,7 +243,153 @@ export class OcctHelper { } } - static wrapShape(shape: TopoDS_Shape): IShape { - return new OccShape(shape); + static getActualShape(shape: TopoDS_Shape): TopoDS_Shape { + switch (shape.shapeType()) { + case wasm.TopAbs_ShapeEnum.TopAbs_COMPOUND: + return wasm.TopoDS.compound(shape); + case wasm.TopAbs_ShapeEnum.TopAbs_COMPSOLID: + return wasm.TopoDS.compsolid(shape); + case wasm.TopAbs_ShapeEnum.TopAbs_SOLID: + return wasm.TopoDS.solid(shape); + case wasm.TopAbs_ShapeEnum.TopAbs_SHELL: + return wasm.TopoDS.shell(shape); + case wasm.TopAbs_ShapeEnum.TopAbs_FACE: + return wasm.TopoDS.face(shape); + case wasm.TopAbs_ShapeEnum.TopAbs_WIRE: + return wasm.TopoDS.wire(shape); + case wasm.TopAbs_ShapeEnum.TopAbs_EDGE: + return wasm.TopoDS.edge(shape); + case wasm.TopAbs_ShapeEnum.TopAbs_VERTEX: + return wasm.TopoDS.vertex(shape); + default: + return shape; + } + } + + static getJoinType(joinType: JoinType) { + switch (joinType) { + case JoinType.arc: + return wasm.GeomAbs_JoinType.GeomAbs_Arc; + case JoinType.intersection: + return wasm.GeomAbs_JoinType.GeomAbs_Intersection; + case JoinType.tangent: + return wasm.GeomAbs_JoinType.GeomAbs_Tangent; + default: + throw new Error("Unknown join type: " + joinType); + } + } + + static wrapShape(shape: TopoDS_Shape, id: string = Id.generate()): IShape { + switch (shape.shapeType()) { + case wasm.TopAbs_ShapeEnum.TopAbs_COMPOUND: + return new OccCompound(wasm.TopoDS.compound(shape), id); + case wasm.TopAbs_ShapeEnum.TopAbs_COMPSOLID: + return new OccCompSolid(wasm.TopoDS.compsolid(shape), id); + case wasm.TopAbs_ShapeEnum.TopAbs_SOLID: + return new OccSolid(wasm.TopoDS.solid(shape), id); + case wasm.TopAbs_ShapeEnum.TopAbs_SHELL: + return new OccShell(wasm.TopoDS.shell(shape), id); + case wasm.TopAbs_ShapeEnum.TopAbs_FACE: + return new OccFace(wasm.TopoDS.face(shape), id); + case wasm.TopAbs_ShapeEnum.TopAbs_WIRE: + return new OccWire(wasm.TopoDS.wire(shape), id); + case wasm.TopAbs_ShapeEnum.TopAbs_EDGE: + return new OccEdge(wasm.TopoDS.edge(shape), id); + case wasm.TopAbs_ShapeEnum.TopAbs_VERTEX: + return new OccVertex(wasm.TopoDS.vertex(shape), id); + default: + return new OccShape(shape, id); + } + } + + static wrapCurve(curve: Geom_Curve): ICurve { + let isType = (type: string) => wasm.Transient.isInstance(curve, type); + if (isType("Geom_Line")) return new OccLine(curve as Geom_Line); + else if (isType("Geom_Circle")) return new OccCircle(curve as Geom_Circle); + else if (isType("Geom_Ellipse")) return new OccEllipse(curve as Geom_Ellipse); + else if (isType("Geom_Hyperbola")) return new OccHyperbola(curve as Geom_Hyperbola); + else if (isType("Geom_Parabola")) return new OccParabola(curve as Geom_Parabola); + else if (isType("Geom_BezierCurve")) return new OccBezierCurve(curve as Geom_BezierCurve); + else if (isType("Geom_BSplineCurve")) return new OccBSplineCurve(curve as Geom_BSplineCurve); + else if (isType("Geom_OffsetCurve")) return new OccOffsetCurve(curve as Geom_OffsetCurve); + else if (isType("Geom_TrimmedCurve")) return new OccTrimmedCurve(curve as Geom_TrimmedCurve); + + throw new Error("Unknown curve type: " + curve); + } + + static getCurveType(curve: Geom_Curve): CurveType { + let isType = (type: string) => wasm.Transient.isInstance(curve, type); + if (isType("Geom_Line")) return CurveType.Line; + else if (isType("Geom_Circle")) return CurveType.Circle; + else if (isType("Geom_Ellipse")) return CurveType.Ellipse; + else if (isType("Geom_Hyperbola")) return CurveType.Hyperbola; + else if (isType("Geom_Parabola")) return CurveType.Parabola; + else if (isType("Geom_BezierCurve")) return CurveType.BezierCurve; + else if (isType("Geom_BSplineCurve")) return CurveType.BSplineCurve; + else if (isType("Geom_OffsetCurve")) return CurveType.OffsetCurve; + else if (isType("Geom_TrimmedCurve")) return CurveType.TrimmedCurve; + + throw new Error("Unknown curve type"); + } + + static wrapSurface(surface: Geom_Surface): ISurface { + let isType = (type: string) => wasm.Transient.isInstance(surface, type); + let actualSurface = surface as any; + if (isType("GeomPlate_Surface")) return new OccPlateSurface(actualSurface); + else if (isType("Geom_Plane")) return new OccPlane(actualSurface); + else if (isType("Geom_SurfaceOfLinearExtrusion")) + return new OccSurfaceOfLinearExtrusion(actualSurface); + else if (isType("Geom_SurfaceOfRevolution")) return new OccSurfaceOfRevolution(actualSurface); + else if (isType("Geom_OffsetSurface")) return new OccOffsetSurface(actualSurface); + else if (isType("Geom_BSplineSurface")) return new OccBSplineSurface(actualSurface); + else if (isType("Geom_BezierSurface")) return new OccBezierSurface(actualSurface); + else if (isType("Geom_CylindricalSurface")) return new OccCylindricalSurface(actualSurface); + else if (isType("Geom_ConicalSurface")) return new OccConicalSurface(actualSurface); + else if (isType("Geom_SphericalSurface")) return new OccSphericalSurface(actualSurface); + else if (isType("Geom_RectangularTrimmedSurface")) return new OccRectangularSurface(actualSurface); + else if (isType("Geom_ToroidalSurface")) return new OccToroidalSurface(actualSurface); + else if (isType("ShapeExtent_CompositeSurface")) return new OccCompositeSurface(actualSurface); + + throw new Error("Unknown surface type: " + surface); + } + + static getSurfaceType(surface: Geom_Surface): SurfaceType { + let isType = (type: string) => wasm.Transient.isInstance(surface, type); + if (isType("GeomPlate_Surface")) return SurfaceType.Plate; + else if (isType("Geom_Plane")) return SurfaceType.Plane; + else if (isType("Geom_SurfaceOfLinearExtrusion")) return SurfaceType.Extrusion; + else if (isType("Geom_SurfaceOfRevolution")) return SurfaceType.Revolution; + else if (isType("Geom_OffsetSurface")) return SurfaceType.Offset; + else if (isType("Geom_BSplineSurface")) return SurfaceType.BSpline; + else if (isType("Geom_BezierSurface")) return SurfaceType.Bezier; + else if (isType("Geom_CylindricalSurface")) return SurfaceType.Cylinder; + else if (isType("Geom_ConicalSurface")) return SurfaceType.Conical; + else if (isType("Geom_SphericalSurface")) return SurfaceType.Spherical; + else if (isType("Geom_RectangularTrimmedSurface")) return SurfaceType.RectangularTrimmed; + else if (isType("Geom_ToroidalSurface")) return SurfaceType.Toroidal; + else if (isType("ShapeExtent_CompositeSurface")) return SurfaceType.Composite; + + throw new Error("Unknown surface type"); + } + + static convertContinuity(cni: GeomAbs_Shape) { + switch (cni) { + case wasm.GeomAbs_Shape.GeomAbs_C0: + return Continuity.C0; + case wasm.GeomAbs_Shape.GeomAbs_G1: + return Continuity.G1; + case wasm.GeomAbs_Shape.GeomAbs_C1: + return Continuity.C1; + case wasm.GeomAbs_Shape.GeomAbs_G2: + return Continuity.G2; + case wasm.GeomAbs_Shape.GeomAbs_C2: + return Continuity.C2; + case wasm.GeomAbs_Shape.GeomAbs_C3: + return Continuity.C3; + case wasm.GeomAbs_Shape.GeomAbs_CN: + return Continuity.CN; + default: + throw new Error("unknown continuity"); + } } } diff --git a/packages/chili-wasm/src/index.ts b/packages/chili-wasm/src/index.ts index e4638e15..3924baf4 100644 --- a/packages/chili-wasm/src/index.ts +++ b/packages/chili-wasm/src/index.ts @@ -1 +1,2 @@ export * from "./wasm"; +export * from "./factory"; diff --git a/packages/chili-wasm/src/mesher.ts b/packages/chili-wasm/src/mesher.ts index 43da2b82..4f6b83a2 100644 --- a/packages/chili-wasm/src/mesher.ts +++ b/packages/chili-wasm/src/mesher.ts @@ -11,15 +11,11 @@ import { OcctHelper } from "./helper"; import { OccShape } from "./shape"; export class Mesher implements IShapeMeshData { - private isEdgeMeshed: boolean = false; - private isFaceMeshed: boolean = false; - private _lines?: EdgeMeshData; private _faces?: FaceMeshData; get edges(): EdgeMeshData | undefined { - if (!this.isEdgeMeshed) { - this.isEdgeMeshed = true; + if (this._lines === undefined) { let edgeMesher = new wasm.EdgeMesher(this.shape.shape, 0.1); this._lines = { lineType: LineType.Solid, @@ -32,8 +28,7 @@ export class Mesher implements IShapeMeshData { return this._lines; } get faces(): FaceMeshData | undefined { - if (!this.isFaceMeshed) { - this.isFaceMeshed = true; + if (this._faces === undefined) { let faceMesher = new wasm.FaceMesher(this.shape.shape, 0.1); this._faces = { positions: faceMesher.getPosition(), @@ -51,18 +46,35 @@ export class Mesher implements IShapeMeshData { constructor(readonly shape: OccShape) {} updateMeshShape(): void { - this.isEdgeMeshed = false; - this.isFaceMeshed = false; + if (this._lines !== undefined) { + wasm.Shape.findSubShapes(this.shape.shape, wasm.TopAbs_ShapeEnum.TopAbs_EDGE).forEach( + (edge, i) => { + let s = this._lines!.groups[i].shape; + this._lines!.groups[i].shape = OcctHelper.wrapShape(edge, s.id); + s.dispose(); + }, + ); + } + if (this._faces !== undefined) { + wasm.Shape.findSubShapes(this.shape.shape, wasm.TopAbs_ShapeEnum.TopAbs_FACE).forEach( + (face, i) => { + let s = this._faces!.groups[i].shape; + this._faces!.groups[i].shape = OcctHelper.wrapShape(face, s.id); + s.dispose(); + }, + ); + } } private getEdgeGroups(mesher: EdgeMesher): ShapeMeshGroup[] { let result: ShapeMeshGroup[] = []; let groups = mesher.getGroups(); - for (let i = 0; i < mesher.getEdgeSize(); i++) { + let edges = mesher.getEdges(); + for (let i = 0; i < edges.length; i++) { result.push({ start: groups[2 * i], count: groups[2 * i + 1], - shape: OcctHelper.wrapShape(mesher.getEdge(i)), + shape: OcctHelper.wrapShape(edges[i]), }); } return result; @@ -71,11 +83,12 @@ export class Mesher implements IShapeMeshData { private getFaceGroups(mesher: FaceMesher): ShapeMeshGroup[] { let result: ShapeMeshGroup[] = []; let groups = mesher.getGroups(); - for (let i = 0; i < mesher.getFaceSize(); i++) { + let faces = mesher.getFaces(); + for (let i = 0; i < faces.length; i++) { result.push({ start: groups[2 * i], count: groups[2 * i + 1], - shape: OcctHelper.wrapShape(mesher.getFace(i)), + shape: OcctHelper.wrapShape(faces[i]), }); } return result; diff --git a/packages/chili-wasm/src/shape.ts b/packages/chili-wasm/src/shape.ts index b737c6b5..34dbf6fd 100644 --- a/packages/chili-wasm/src/shape.ts +++ b/packages/chili-wasm/src/shape.ts @@ -1,27 +1,94 @@ -import { IEdge, IShape, IShapeMeshData, IWire, Matrix4, Orientation, Plane, ShapeType } from "chili-core"; -import { TopoDS_Shape, Shape } from "../lib/chili-wasm"; +import { + ICurve, + Id, + IEdge, + IShape, + IShapeMeshData, + ITrimmedCurve, + IWire, + Matrix4, + Orientation, + Plane, + Ray, + Result, + ShapeType, + XYZ, + gc, + IFace, + ISurface, + JoinType, + MathUtils, + IShell, + ISolid, + ICompoundSolid, + ICompound, + SerializedProperties, + Serializer, + IVertex, +} from "chili-core"; +import { + TopoDS_Edge, + TopoDS_Face, + TopoDS_Shape, + TopoDS_Shell, + TopoDS_Vertex, + TopoDS_Wire, +} from "../lib/chili-wasm"; import { OcctHelper } from "./helper"; import { Mesher } from "./mesher"; +import { OccCurve, OccTrimmedCurve } from "./curve"; +import { OccShapeConverter } from "./converter"; +@Serializer.register(["shape", "id"], OccShape.deserialize, OccShape.serialize) export class OccShape implements IShape { + static serialize(target: OccShape): SerializedProperties { + return { + shape: new OccShapeConverter().convertToBrep(target).ok(), + id: target.id, + }; + } + + static deserialize(shape: string, id: string) { + let tshape = new OccShapeConverter().convertFromBrep(shape).ok() as OccShape; + tshape._id = id; + return tshape; + } + readonly shapeType: ShapeType; - readonly mesh: IShapeMeshData; + protected _mesh: IShapeMeshData | undefined; + get mesh(): IShapeMeshData { + if (!this._mesh) { + this._mesh = new Mesher(this); + } + return this._mesh; + } protected _shape: TopoDS_Shape; get shape(): TopoDS_Shape { return this._shape; } + protected _id: string; get id(): string { - throw new Error("Method not implemented."); + return this._id; + } + + get matrix(): Matrix4 { + return OcctHelper.convertToMatrix(this.shape.getLocation().transformation()); } - matrix: Matrix4; - constructor(shape: TopoDS_Shape) { + set matrix(matrix: Matrix4) { + gc((c) => { + let location = new wasm.TopLoc_Location(OcctHelper.convertFromMatrix(matrix)); + this._shape.setLocation(location, false); + this._mesh?.updateMeshShape(); + }); + } + + constructor(shape: TopoDS_Shape, id?: string) { + this._id = id ?? Id.generate(); this._shape = shape; this.shapeType = OcctHelper.getShapeType(shape); - this.mesh = new Mesher(this); - this.matrix = new Matrix4(); } isClosed(): boolean { @@ -74,16 +141,27 @@ export class OccShape implements IShape { ); } - iterSubShapes(shapeType: ShapeType, unique: boolean): IterableIterator { - throw new Error("Method not implemented."); - } - section(shape: IShape | Plane): IShape { - throw new Error("Method not implemented."); + if (shape instanceof OccShape) { + let section = wasm.Shape.sectionSS(this.shape, shape.shape); + return OcctHelper.wrapShape(section); + } + if (shape instanceof Plane) { + let section = wasm.Shape.sectionSP(this.shape, OcctHelper.toPln(shape)); + return OcctHelper.wrapShape(section); + } + + throw new Error("Unsupported type"); } split(edges: (IEdge | IWire)[]): IShape { - throw new Error("Method not implemented."); + let shapes = edges.map((x) => { + if (x instanceof OccShape) { + return x.shape; + } + throw new Error("Unsupported type"); + }); + return OcctHelper.wrapShape(wasm.Shape.splitByEdgeOrWires(this.shape, shapes)); } dispose(): void { @@ -91,3 +169,156 @@ export class OccShape implements IShape { this._shape = null as any; } } + +@Serializer.register(["shape", "id"], OccShape.deserialize, OccShape.serialize) +export class OccVertex extends OccShape implements IVertex { + readonly vertex: TopoDS_Vertex; + + constructor(shape: TopoDS_Vertex, id?: string) { + super(shape, id); + this.vertex = shape; + } +} + +@Serializer.register(["shape", "id"], OccShape.deserialize, OccShape.serialize) +export class OccEdge extends OccShape implements IEdge { + private _edge: TopoDS_Edge; + get edge(): TopoDS_Edge { + return this._edge; + } + + constructor(shape: TopoDS_Edge, id?: string) { + super(shape, id); + this._edge = shape; + } + + update(curve: ICurve): void { + if (!(curve instanceof OccCurve)) { + throw new Error("Invalid curve"); + } + this._shape = wasm.Edge.fromCurve(curve.curve); + this._mesh = undefined; + } + + intersect(other: IEdge | Ray): { parameter: number; point: XYZ }[] { + return gc((c) => { + let edge: TopoDS_Edge | undefined = undefined; + if (other instanceof OccEdge) { + edge = other.edge; + } + if (other instanceof Ray) { + let line = c(wasm.Curve.makeLine(other.location, other.direction)); + edge = c(wasm.Edge.fromCurve(line.get())); + } + if (edge === undefined) { + throw new Error("Unsupported type"); + } + return wasm.Edge.intersect(this.edge, edge).map((x) => ({ + parameter: x.parameter, + point: OcctHelper.toXYZ(x.point), + })); + }); + } + + length(): number { + return wasm.Edge.curveLength(this.edge); + } + + curve(): ITrimmedCurve { + return gc((c) => { + let curve = c(wasm.Edge.curve(this.edge)); + return new OccTrimmedCurve(curve.get()!); + }); + } + + offset(distance: number, dir: XYZ): Result { + return gc((c) => { + let occDir = c(OcctHelper.toDir(dir)); + let edge = wasm.Edge.offset(this.edge, occDir, distance); + if (edge.isNull()) { + return Result.err("Offset failed"); + } + return Result.ok(OcctHelper.wrapShape(edge)); + }); + } + + trim(start: number, end: number): IEdge { + let newEdge = wasm.Edge.trim(this.edge, start, end); + return new OccEdge(newEdge); + } +} + +@Serializer.register(["shape", "id"], OccShape.deserialize, OccShape.serialize) +export class OccWire extends OccShape implements IWire { + constructor( + readonly wire: TopoDS_Wire, + id?: string, + ) { + super(wire, id); + } + + toFace(): Result { + let face = wasm.Wire.makeFace(this.wire); + if (face.isNull()) { + return Result.err("To face failed"); + } + return Result.ok(new OccFace(face)); + } + + offset(distance: number, joinType: JoinType): Result { + let offseted = wasm.Wire.offset(this.wire, distance, OcctHelper.getJoinType(joinType)); + if (offseted.isNull()) { + return Result.err("Offset failed"); + } + return Result.ok(OcctHelper.wrapShape(offseted)); + } +} + +@Serializer.register(["shape", "id"], OccShape.deserialize, OccShape.serialize) +export class OccFace extends OccShape implements IFace { + constructor( + readonly face: TopoDS_Face, + id?: string, + ) { + super(face, id); + } + normal(u: number, v: number): [point: XYZ, normal: XYZ] { + return gc((c) => { + let pnt = c(new wasm.gp_Pnt(0, 0, 0)); + let normal = c(new wasm.gp_Vec(0, 0, 0)); + wasm.Face.normal(this.shape, u, v, pnt, normal); + return [OcctHelper.toXYZ(pnt), OcctHelper.toXYZ(normal)]; + }); + } + outerWire(): IWire { + return new OccWire(wasm.Face.outerWire(this.face)); + } + surface(): ISurface { + return gc((c) => { + let handleSurface = c(wasm.Face.surface(this.face)); + return OcctHelper.wrapSurface(handleSurface.get()!); + }); + } + segmentsOfEdgeOnFace(edge: IEdge): undefined | { start: number; end: number } { + if (edge instanceof OccEdge) { + let domain = wasm.Face.curveOnSurface(this.face, edge.edge); + if (MathUtils.allEqualZero(domain.start, domain.end)) { + return undefined; + } + return domain; + } + return undefined; + } +} + +@Serializer.register(["shape", "id"], OccShape.deserialize, OccShape.serialize) +export class OccShell extends OccShape implements IShell {} + +@Serializer.register(["shape", "id"], OccShape.deserialize, OccShape.serialize) +export class OccSolid extends OccShape implements ISolid {} + +@Serializer.register(["shape", "id"], OccShape.deserialize, OccShape.serialize) +export class OccCompSolid extends OccShape implements ICompoundSolid {} + +@Serializer.register(["shape", "id"], OccShape.deserialize, OccShape.serialize) +export class OccCompound extends OccShape implements ICompound {} diff --git a/packages/chili-wasm/src/surface.ts b/packages/chili-wasm/src/surface.ts new file mode 100644 index 00000000..3a6c7c71 --- /dev/null +++ b/packages/chili-wasm/src/surface.ts @@ -0,0 +1,498 @@ +// Copyright 2022-2023 the Chili authors. All rights reserved. AGPL-3.0 license. + +import { + Continuity, + IBSplineSurface, + IBezierSurface, + IBoundedSurface, + ICompositeSurface, + IConicalSurface, + ICurve, + ICylindricalSurface, + IElementarySurface, + IGeometry, + IOffsetSurface, + IPlaneSurface, + IPlateSurface, + IRectangularTrimmedSurface, + ISphericalSurface, + ISurface, + ISurfaceOfLinearExtrusion, + ISurfaceOfRevolution, + ISweptSurface, + IToroidalSurface, + Plane, + XYZ, + gc, +} from "chili-core"; +import { + GeomPlate_Surface, + Geom_BSplineSurface, + Geom_BezierSurface, + Geom_ConicalSurface, + Geom_CylindricalSurface, + Geom_ElementarySurface, + Geom_OffsetSurface, + Geom_Plane, + Geom_RectangularTrimmedSurface, + Geom_SphericalSurface, + Geom_Surface, + Geom_SurfaceOfLinearExtrusion, + Geom_SurfaceOfRevolution, + Geom_SweptSurface, + Geom_ToroidalSurface, + ShapeExtend_CompositeSurface, +} from "../lib/chili-wasm"; +import { OccCurve } from "./curve"; +import { OccGeometry } from "./geometry"; +import { OcctHelper } from "./helper"; + +export class OccSurface extends OccGeometry implements ISurface { + constructor(readonly surface: Geom_Surface) { + super(surface); + } + + override copy(): IGeometry { + return OcctHelper.wrapSurface(this.surface); + } + + projectCurve(curve: ICurve): ICurve | undefined { + return gc((c) => { + if (!(curve instanceof OccCurve)) return undefined; + let handleCurve = c(wasm.Surface.projectCurve(this.surface, curve.curve)); + return OcctHelper.wrapCurve(handleCurve.get()!); + }); + } + + project(point: XYZ): XYZ[] { + return wasm.Surface.projectPoint(this.surface, point) + .map((p) => new XYZ(p.x, p.y, p.z)) + .toSorted((a, b) => a.distanceTo(point) - b.distanceTo(point)); + } + + isPlanar(): boolean { + return wasm.Surface.isPlanar(this.surface); + } + + parameter(point: XYZ, maxDistance: number): { u: number; v: number } | undefined { + return wasm.Surface.parameters(this.surface, point, maxDistance); + } + + nearestPoint(point: XYZ): [XYZ, number] | undefined { + let result = wasm.Surface.nearestPoint(this.surface, point); + if (result) { + return [OcctHelper.toXYZ(result.point), result.parameter]; + } + return undefined; + } + + continuity(): Continuity { + return OcctHelper.convertContinuity(this.surface.continuity()); + } + + uIso(u: number): ICurve { + return gc((c) => { + let curve = c(this.surface.uIso(u)); + return OcctHelper.wrapCurve(curve.get()!); + }); + } + vIso(v: number): ICurve { + return gc((c) => { + let curve = c(this.surface.vIso(v)); + return OcctHelper.wrapCurve(curve.get()!); + }); + } + isUClosed(): boolean { + return this.surface.isUClosed(); + } + isVClosed(): boolean { + return this.surface.isVClosed(); + } + isUPreiodic(): boolean { + return this.surface.isUPeriodic(); + } + isVPreiodic(): boolean { + return this.surface.isVPeriodic(); + } + vPeriod(): number { + return this.surface.vPeriod(); + } + uPeriod(): number { + return this.surface.uPeriod(); + } + bounds() { + return wasm.Surface.bounds(this.surface); + } + isCNu(n: number): boolean { + return this.surface.isCNu(n); + } + isCNv(n: number): boolean { + return this.surface.isCNv(n); + } + d0(u: number, v: number): XYZ { + return gc((c) => { + let pnt = c(new wasm.gp_Pnt(0, 0, 0)); + this.surface.d0(u, v, pnt); + return OcctHelper.toXYZ(pnt); + }); + } + d1( + u: number, + v: number, + ): { + point: XYZ; + d1u: XYZ; + d1v: XYZ; + } { + return gc((c) => { + let pnt = c(new wasm.gp_Pnt(0, 0, 0)); + let d1u = c(new wasm.gp_Vec(0, 0, 0)); + let d1v = c(new wasm.gp_Vec(0, 0, 0)); + this.surface.d1(u, v, pnt, d1u, d1v); + return { + point: OcctHelper.toXYZ(pnt), + d1u: OcctHelper.toXYZ(d1u), + d1v: OcctHelper.toXYZ(d1v), + }; + }); + } + d2(u: number, v: number) { + return gc((c) => { + let pnt = c(new wasm.gp_Pnt(0, 0, 0)); + let d1u = c(new wasm.gp_Vec(0, 0, 0)); + let d1v = c(new wasm.gp_Vec(0, 0, 0)); + let d2u = c(new wasm.gp_Vec(0, 0, 0)); + let d2v = c(new wasm.gp_Vec(0, 0, 0)); + let d2uv = c(new wasm.gp_Vec(0, 0, 0)); + this.surface.d2(u, v, pnt, d1u, d1v, d2u, d2v, d2uv); + + return { + point: OcctHelper.toXYZ(pnt), + d1u: OcctHelper.toXYZ(d1u), + d1v: OcctHelper.toXYZ(d1v), + d2u: OcctHelper.toXYZ(d2u), + d2v: OcctHelper.toXYZ(d2v), + d2uv: OcctHelper.toXYZ(d2uv), + }; + }); + } + d3(u: number, v: number) { + return gc((c) => { + let pnt = c(new wasm.gp_Pnt(0, 0, 0)); + let d1u = c(new wasm.gp_Vec(0, 0, 0)); + let d1v = c(new wasm.gp_Vec(0, 0, 0)); + let d2u = c(new wasm.gp_Vec(0, 0, 0)); + let d2v = c(new wasm.gp_Vec(0, 0, 0)); + let d2uv = c(new wasm.gp_Vec(0, 0, 0)); + let d3u = c(new wasm.gp_Vec(0, 0, 0)); + let d3v = c(new wasm.gp_Vec(0, 0, 0)); + let d3uuv = c(new wasm.gp_Vec(0, 0, 0)); + let d3uvv = c(new wasm.gp_Vec(0, 0, 0)); + this.surface.d3(u, v, pnt, d1u, d1v, d2u, d2v, d2uv, d3u, d3v, d3uuv, d3uvv); + + return { + point: OcctHelper.toXYZ(pnt), + d1u: OcctHelper.toXYZ(d1u), + d1v: OcctHelper.toXYZ(d1v), + d2u: OcctHelper.toXYZ(d2u), + d2v: OcctHelper.toXYZ(d2v), + d2uv: OcctHelper.toXYZ(d2uv), + d3u: OcctHelper.toXYZ(d3u), + d3v: OcctHelper.toXYZ(d3v), + d3uuv: OcctHelper.toXYZ(d3uuv), + d3uvv: OcctHelper.toXYZ(d3uvv), + }; + }); + } + dn(u: number, v: number, nu: number, nv: number): XYZ { + return gc((c) => { + let vec = c(this.surface.dn(u, v, nu, nv)); + return OcctHelper.toXYZ(vec); + }); + } + value(u: number, v: number): XYZ { + return gc((c) => { + let pnt = c(this.surface.value(u, v)); + return OcctHelper.toXYZ(pnt); + }); + } +} + +export class OccPlateSurface extends OccSurface implements IPlateSurface { + constructor(private plateSurface: GeomPlate_Surface) { + super(plateSurface); + } + + setBounds(u1: number, u2: number, v1: number, v2: number): void { + this.plateSurface.setBounds(u1, u2, v1, v2); + } +} + +export class OccBoundedSurface extends OccSurface implements IBoundedSurface {} + +export class OccElementarySurface extends OccSurface implements IElementarySurface { + constructor(private elementarySurface: Geom_ElementarySurface) { + super(elementarySurface); + } + + get location() { + return gc((c) => OcctHelper.toXYZ(c(this.elementarySurface.location()))); + } + set location(value: XYZ) { + gc((c) => { + this.elementarySurface.setLocation(c(OcctHelper.toPnt(value))); + }); + } + + get axis() { + return gc((c) => { + return OcctHelper.toXYZ(c(c(this.elementarySurface.axis()).direction)); + }); + } + set axis(value: XYZ) { + gc((c) => { + let pnt = c(this.elementarySurface.location()); + let axis = c(new wasm.gp_Ax1(pnt, c(OcctHelper.toDir(value)))); + this.elementarySurface.setAxis(axis); + }); + } + get coordinates() { + return gc((c) => { + return OcctHelper.fromAx23(c(this.elementarySurface.position())); + }); + } + set coordinates(value: Plane) { + gc((c) => { + this.elementarySurface.setPosition(c(OcctHelper.toAx3(value))); + }); + } +} + +export class OccOffsetSurface extends OccSurface implements IOffsetSurface { + constructor(private offsetSurface: Geom_OffsetSurface) { + super(offsetSurface); + } + get offset(): number { + return this.offsetSurface.offset(); + } + set offset(value: number) { + this.offsetSurface.setOffsetValue(value); + } + get basisSurface() { + return gc((c) => { + let handleSurface = c(this.offsetSurface.basisSurface()); + return OcctHelper.wrapSurface(handleSurface.get()!); + }); + } + set basisSurface(value: ISurface) { + gc((c) => { + if (value instanceof OccSurface) { + let handleSurface = c(new wasm.Handle_Geom_Surface(value.surface)); + this.offsetSurface.setBasisSurface(handleSurface, true); + } + throw new Error("Invalid surface type"); + }); + } +} + +export class OccSweptSurface extends OccSurface implements ISweptSurface { + constructor(private sweptSurface: Geom_SweptSurface) { + super(sweptSurface); + } + direction(): XYZ { + return gc((c) => { + return OcctHelper.toXYZ(c(this.sweptSurface.direction())); + }); + } + basisCurve(): ICurve { + return gc((c) => { + let handleCurve = this.sweptSurface.basisCurve(); + return OcctHelper.wrapCurve(handleCurve.get()!); + }); + } +} + +export class OccCompositeSurface extends OccSurface implements ICompositeSurface { + constructor(compositeSurface: ShapeExtend_CompositeSurface) { + super(compositeSurface as any); + } +} + +export class OccBSplineSurface extends OccSurface implements IBSplineSurface { + constructor(private bsplineSurface: Geom_BSplineSurface) { + super(bsplineSurface); + } +} + +export class OccBezierSurface extends OccSurface implements IBezierSurface { + constructor(private bezierSurface: Geom_BezierSurface) { + super(bezierSurface); + } +} + +export class OccRectangularSurface extends OccSurface implements IRectangularTrimmedSurface { + constructor(private rectangularSurface: Geom_RectangularTrimmedSurface) { + super(rectangularSurface); + } + basisSurface(): ISurface { + return gc((c) => { + let handleSurface = c(this.rectangularSurface.basisSurface()); + return OcctHelper.wrapSurface(handleSurface.get()!); + }); + } + setUTrim(u1: number, u2: number): void { + this.rectangularSurface.setTrim2(u1, u2, true, true); + } + setVTrim(v1: number, v2: number): void { + this.rectangularSurface.setTrim2(v1, v2, false, true); + } + setTrim(u1: number, u2: number, v1: number, v2: number): void { + this.rectangularSurface.setTrim(u1, u2, v1, v2, true, true); + } +} + +export class OccConicalSurface extends OccElementarySurface implements IConicalSurface { + constructor(private conicalSurface: Geom_ConicalSurface) { + super(conicalSurface); + } + get semiAngle(): number { + return this.conicalSurface.semiAngle(); + } + set semiAngle(value: number) { + this.conicalSurface.setSemiAngle(value); + } + setRadius(value: number) { + return this.conicalSurface.setRadius(value); + } + apex(): XYZ { + return gc((c) => { + return OcctHelper.toXYZ(c(this.conicalSurface.apex())); + }); + } + refRadius(): number { + return this.conicalSurface.refRadius(); + } +} + +export class OccCylindricalSurface extends OccElementarySurface implements ICylindricalSurface { + constructor(private cylindricalSurface: Geom_CylindricalSurface) { + super(cylindricalSurface); + } + get radius(): number { + return this.cylindricalSurface.radius(); + } + set radius(value: number) { + this.cylindricalSurface.setRadius(value); + } +} + +export class OccPlane extends OccElementarySurface implements IPlaneSurface { + constructor(private geom_plane: Geom_Plane) { + super(geom_plane); + } + get plane(): Plane { + return gc((c) => { + return OcctHelper.fromPln(c(this.geom_plane.pln())); + }); + } + set plane(value: Plane) { + gc((c) => { + this.geom_plane.setPln(c(OcctHelper.toPln(value))); + }); + } +} + +export class OccSphericalSurface extends OccElementarySurface implements ISphericalSurface { + constructor(private sphericalSurface: Geom_SphericalSurface) { + super(sphericalSurface); + } + get radius(): number { + return this.sphericalSurface.radius(); + } + set radius(value: number) { + this.sphericalSurface.setRadius(value); + } + area(): number { + return this.sphericalSurface.area(); + } + volume(): number { + return this.sphericalSurface.volume(); + } +} + +export class OccToroidalSurface extends OccElementarySurface implements IToroidalSurface { + constructor(private toroidalSurface: Geom_ToroidalSurface) { + super(toroidalSurface); + } + area(): number { + return this.toroidalSurface.area(); + } + volume(): number { + return this.toroidalSurface.volume(); + } + get majorRadius(): number { + return this.toroidalSurface.majorRadius(); + } + set majorRadius(value: number) { + this.toroidalSurface.setMajorRadius(value); + } + get minorRadius(): number { + return this.toroidalSurface.minorRadius(); + } + set minorRadius(value: number) { + this.toroidalSurface.setMinorRadius(value); + } +} + +export class OccSurfaceOfLinearExtrusion extends OccSweptSurface implements ISurfaceOfLinearExtrusion { + constructor(private surfaceOfLinearExtrusion: Geom_SurfaceOfLinearExtrusion) { + super(surfaceOfLinearExtrusion); + } + setDirection(direction: XYZ) { + gc((c) => { + this.surfaceOfLinearExtrusion.setDirection(c(OcctHelper.toDir(direction))); + }); + } + setBasisCurve(curve: ICurve) { + if (!(curve instanceof OccCurve)) { + throw new Error("curve must be an OccCurve"); + } + let handleCurve = new wasm.Handle_Geom_Curve(curve.curve); + this.surfaceOfLinearExtrusion.setBasisCurve(handleCurve); + handleCurve.delete(); + } +} + +export class OccSurfaceOfRevolution extends OccSweptSurface implements ISurfaceOfRevolution { + constructor(private surfaceOfRevolution: Geom_SurfaceOfRevolution) { + super(surfaceOfRevolution); + } + get location(): XYZ { + return gc((c) => { + return OcctHelper.toXYZ(c(this.surfaceOfRevolution.location())); + }); + } + set location(value: XYZ) { + gc((c) => { + this.surfaceOfRevolution.setLocation(c(OcctHelper.toPnt(value))); + }); + } + referencePlane(): Plane { + return gc((c) => { + return OcctHelper.fromAx23(c(this.surfaceOfRevolution.referencePlane())); + }); + } + setDirection(direction: XYZ) { + gc((c) => { + this.surfaceOfRevolution.setDirection(c(OcctHelper.toDir(direction))); + }); + } + setBasisCurve(curve: ICurve) { + if (!(curve instanceof OccCurve)) { + throw new Error("curve must be an OccCurve"); + } + let handleCurve = new wasm.Handle_Geom_Curve(curve.curve); + this.surfaceOfRevolution.setBasisCurve(handleCurve); + handleCurve.delete(); + } +} diff --git a/packages/chili-web/src/index.ts b/packages/chili-web/src/index.ts index f01d9e67..b0ffb76e 100644 --- a/packages/chili-web/src/index.ts +++ b/packages/chili-web/src/index.ts @@ -10,7 +10,7 @@ document.body.appendChild(loading); // prettier-ignore new AppBuilder() .useIndexedDB() - .useOcc() + // .useOcc() .useNewOcc() .useThree() .useUI() diff --git a/packages/chili/src/commands/application/performanceTest.ts b/packages/chili/src/commands/application/performanceTest.ts index 61fa7ed0..80a270fa 100644 --- a/packages/chili/src/commands/application/performanceTest.ts +++ b/packages/chili/src/commands/application/performanceTest.ts @@ -55,56 +55,13 @@ export class OccPerformanceTestCommand extends PerformanceTestCommand { private index = 1; shapes: any[] = []; - protected override createShape(document: IDocument, material: Material, p: XYZ): void { - // let plane = Plane.XY.translateTo(position); - // let box = document.application.shapeFactory - // .box(plane, this.size * Math.random(), this.size * Math.random(), this.size * Math.random()) - // .ok(); - // let f = box.mesh.faces; - // let e = box.mesh.edges; - // let entity = new EditableGeometryEntity(document, box.ok(), material.id); - // let model = new GeometryModel(document, `box ${this.index++}`, entity); - // document.addNode(model); - - let wasm = (document.application.shapeFactory as any).wasm; - let point1 = new wasm.gp_Pnt(p.x, p.y, p.z); - let direction = new wasm.gp_Dir(0, 0, 1); - let ax2 = new wasm.gp_Ax2(point1, direction); - let box = wasm.ShapeFactory.makeBox(ax2, this.size, this.size, this.size); - let faces = new wasm.FaceMesher(box, 0.1); - let edges = new wasm.EdgeMesher(box, 0.1); - point1.delete(); - direction.delete(); - ax2.delete(); - this.shapes.push({ - faces, - edges, - box, - }); - - let positions = faces.getPosition(); - let indices = faces.getIndex(); - let normals = faces.getNormal(); - - document.visual.context.displayMesh( - { - positions: edges.getPosition(), - groups: [], - color: 0xfff, - lineType: LineType.Solid, - } as EdgeMeshData, - { - positions: positions as any, - groups: [], - color: 0xfff, - uvs: faces.getUV(), - indices, - normals, - } as FaceMeshData, - ); + protected override createShape(document: IDocument, material: Material, position: XYZ): void { + let plane = Plane.XY.translateTo(position); + let box = document.application.shapeFactory + .box(plane, this.size * Math.random(), this.size * Math.random(), this.size * Math.random()) + .ok(); + let entity = new EditableGeometryEntity(document, box, material.id); + let model = new GeometryModel(document, `box ${this.index++}`, entity); + document.addNode(model); } } - -// export class ThreePerformanceTestCommand extends PerformanceTestCommand { - -// }