diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt index eec7115..c076f9b 100644 --- a/backend/CMakeLists.txt +++ b/backend/CMakeLists.txt @@ -8,6 +8,8 @@ include_directories(${OCE_INCLUDE_DIRS}) add_executable(cad_to_gcode src/cad_to_gcode.cpp) add_executable(iges_to_topo src/iges_to_topo.cpp) +add_executable(shape_to_bspline src/shape_to_bspline.cpp) target_link_libraries(cad_to_gcode ${OpenCASCADE_LIBRARIES}) target_link_libraries(iges_to_topo ${OpenCASCADE_LIBRARIES}) +target_link_libraries(shape_to_bspline ${OpenCASCADE_LIBRARIES}) diff --git a/backend/src/shape_to_bspline.cpp b/backend/src/shape_to_bspline.cpp new file mode 100644 index 0000000..dc819bf --- /dev/null +++ b/backend/src/shape_to_bspline.cpp @@ -0,0 +1,104 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +bool VerticesMatch(const TopoDS_Vertex& v1, const TopoDS_Vertex& v2) { + gp_Pnt p1 = BRep_Tool::Pnt(v1); + gp_Pnt p2 = BRep_Tool::Pnt(v2); + return p1.IsEqual(p2, Precision::Confusion()); +} + +std::vector OrderEdges(const TopoDS_Shape& shape) { + std::vector unorderedEdges, orderedEdges; + + // Fill unorderedEdges with all edges in the shape + for (TopExp_Explorer exp(shape, TopAbs_EDGE); exp.More(); exp.Next()) { + unorderedEdges.push_back(TopoDS::Edge(exp.Current())); + } + + if (unorderedEdges.empty()) return orderedEdges; + + // Start with a random edge + orderedEdges.push_back(unorderedEdges.front()); + unorderedEdges.erase(unorderedEdges.begin()); + + while (!unorderedEdges.empty()) { + bool matchFound = false; + + TopoDS_Vertex startV, endV; + TopExp::Vertices(orderedEdges.front(), startV, endV); // Get start/end vertices of the current path + + for (auto it = unorderedEdges.begin(); it != unorderedEdges.end(); ++it) { + TopoDS_Vertex startVNext, endVNext; + TopExp::Vertices(*it, startVNext, endVNext); // Get vertices of the next candidate edge + + if (VerticesMatch(endV, startVNext)) { // Match end to start + orderedEdges.push_back(*it); // Place it at the end + endV = endVNext; // Update end vertex of the path + unorderedEdges.erase(it); + matchFound = true; + break; + } else if (VerticesMatch(startV, endVNext)) { // Match start to end + orderedEdges.insert(orderedEdges.begin(), *it); // Place it at the beginning + startV = startVNext; // Update start vertex of the path + unorderedEdges.erase(it); + matchFound = true; + break; + } + } + + if (!matchFound) { + break; + } + } + + return orderedEdges; +} + +// Function to sample points from an edge +std::vector SamplePointsFromEdge(const TopoDS_Edge& edge, int numPoints) { + std::vector points; + double first, last; + Handle(Geom_Curve) curve = BRep_Tool::Curve(edge, first, last); + if (!curve.IsNull()) { + double step = (last - first) / (numPoints - 1); + for (int i = 0; i < numPoints; ++i) { + gp_Pnt pnt = curve->Value(first + i * step); + points.push_back(pnt); + } + } + return points; +} + +Handle(Geom_BSplineCurve) CreateBSplineFromShape(const TopoDS_Shape& shape) { + std::vector orderedEdges = OrderEdges(shape); + std::vector allPoints; + const int SAMPLE_NUM = 10; + + for (const auto& edge : orderedEdges) { + std::vector edgePoints = SamplePointsFromEdge(edge, SAMPLE_NUM); + allPoints.insert(allPoints.end(), edgePoints.begin(), edgePoints.end()); + } + + // Convert std::vector to TColgp_Array1OfPnt + TColgp_Array1OfPnt arrayPoints(1, allPoints.size()); + for (Standard_Integer i = 0; i < allPoints.size(); ++i) { + arrayPoints.SetValue(i + 1, allPoints[i]); + } + + GeomAPI_PointsToBSpline splineBuilder(arrayPoints); + return splineBuilder.Curve(); +} +