From 57964102bc0cfb69d80c47e82bc86ad9d4af517b Mon Sep 17 00:00:00 2001 From: "saumya.jain" Date: Fri, 19 Sep 2025 09:42:53 +0200 Subject: [PATCH 1/4] Add debug logging to nestWrapper and improve item handling in JS bindings --- libnest2d_js/libnest2d_js.cpp | 82 +++++++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 4 deletions(-) diff --git a/libnest2d_js/libnest2d_js.cpp b/libnest2d_js/libnest2d_js.cpp index dd99ab24..d4667b19 100644 --- a/libnest2d_js/libnest2d_js.cpp +++ b/libnest2d_js/libnest2d_js.cpp @@ -9,10 +9,13 @@ #include #include #include +#include +#include using namespace emscripten; using namespace libnest2d; using namespace placers; +using namespace selections; // Type aliases to match Python bindings using Point = PointImpl; @@ -73,23 +76,66 @@ std::vector jsArrayToPointVector(const emscripten::val& jsArray) { // Wrapper function for nest() to handle JavaScript arrays ResultAndItem nestWrapper(ItemList jsItems, const Box& bin) { + std::cerr << "[DEBUG] nestWrapper called" << std::endl; + // Convert JavaScript array to std::vector std::vector items; auto length = jsItems["length"].as(); items.reserve(length); + std::cerr << "[DEBUG] Processing " << length << " items" << std::endl; + std::cerr << "[DEBUG] Bin dimensions: " << bin.width() << "x" << bin.height() << std::endl; + for (unsigned i = 0; i < length; i++) { Item item = jsItems[i].as(); items.push_back(item); + std::cerr << "[DEBUG] Item " << i << " - area: " << item.area() + << ", vertexCount: " << item.vertexCount() + << ", binId: " << item.binId() << std::endl; + } + + std::cerr << "[DEBUG] Calling nest() function" << std::endl; + + size_t result = 0; + try { + // Use the _Nester class directly with explicit strategies + using Placer = BottomLeftPlacer; + using Selector = FirstFitSelection; + + std::cerr << "[DEBUG] Creating nester with BottomLeftPlacer and FirstFitSelection" << std::endl; + _Nester nester(bin); + + std::cerr << "[DEBUG] Executing nesting..." << std::endl; + result = nester.execute(items.begin(), items.end()); + + std::cerr << "[DEBUG] Nesting completed, result: " << result << std::endl; + + // Get the pack result + auto& packResult = nester.lastResult(); + std::cerr << "[DEBUG] Pack result has " << packResult.size() << " bins" << std::endl; + + } catch (const std::exception& e) { + std::cerr << "[ERROR] Exception during nesting: " << e.what() << std::endl; + result = 0; + } catch (...) { + std::cerr << "[ERROR] Unknown exception during nesting" << std::endl; + result = 0; } - size_t result = nest(items, bin); + std::cerr << "[DEBUG] nest() returned: " << result << std::endl; + + // Check the state of items after nesting + for (size_t i = 0; i < items.size(); ++i) { + std::cerr << "[DEBUG] After nest - Item " << i << " binId: " << items[i].binId() + << ", translation: (" << getX(items[i].translation()) << ", " << getY(items[i].translation()) << ")" << std::endl; + } // Copy results back to original JavaScript items for (size_t i = 0; i < items.size() && i < length; ++i) { jsItems.set(i, val(items[i])); } + std::cerr << "[DEBUG] Returning result: " << result << std::endl; return resultAndItems(result, jsItems); } @@ -165,7 +211,35 @@ EMSCRIPTEN_BINDINGS(libnest2d_js) { std::vector vertices = jsArrayToPointVector(jsVertices); PolygonImpl polygon; polygon.Contour = vertices; - return Item(polygon); + + // Check if we need to reverse the orientation + // For libnest2d with Clipper, we want the area to be positive + double area = sl::area(polygon); + std::cerr << "[DEBUG] Initial polygon area: " << area << std::endl; + + if (area < 0) { + std::cerr << "[DEBUG] Area is negative, reversing vertex order" << std::endl; + std::reverse(vertices.begin(), vertices.end()); + polygon.Contour = vertices; + + // Verify the area is now positive + double newArea = sl::area(polygon); + std::cerr << "[DEBUG] Area after reversal: " << newArea << std::endl; + + for (size_t i = 0; i < vertices.size(); ++i) { + std::cerr << "[DEBUG] Fixed Vertex " << i << ": (" << getX(vertices[i]) << ", " << getY(vertices[i]) << ")" << std::endl; + } + } else { + std::cerr << "[DEBUG] Area is already positive, no reversal needed" << std::endl; + } + + Item item(polygon); + + std::cerr << "[DEBUG] Created item - area: " << item.area() + << ", vertexCount: " << item.vertexCount() + << ", binId: " << item.binId() << std::endl; + + return item; })) .function("binId", select_overload(&Item::binId)) .function("setBinId", select_overload(&Item::binId)) @@ -196,7 +270,7 @@ EMSCRIPTEN_BINDINGS(libnest2d_js) { .constructor() .function("toDegrees", &Radians::toDegrees); - // Degrees class for rotation angles + // Degrees class for rotation angles class_("Degrees") .constructor() .function("toRadians", &Degrees::toRadians); @@ -210,4 +284,4 @@ EMSCRIPTEN_BINDINGS(libnest2d_js) { function("nest", &nestWrapper); } -#endif // LIBNEST2D_JS_H \ No newline at end of file +#endif // LIBNEST2D_JS_H From 03855c9d31c04d862c57d2eac48caf0c21709ace Mon Sep 17 00:00:00 2001 From: "saumya.jain" Date: Fri, 19 Sep 2025 09:49:19 +0200 Subject: [PATCH 2/4] Refactor vertex processing in JS bindings to iterate in reverse and simplify item creation --- libnest2d_js/libnest2d_js.cpp | 32 ++------------------------------ 1 file changed, 2 insertions(+), 30 deletions(-) diff --git a/libnest2d_js/libnest2d_js.cpp b/libnest2d_js/libnest2d_js.cpp index d4667b19..cd047d85 100644 --- a/libnest2d_js/libnest2d_js.cpp +++ b/libnest2d_js/libnest2d_js.cpp @@ -63,7 +63,7 @@ std::vector jsArrayToPointVector(const emscripten::val& jsArray) { unsigned length = jsArray["length"].as(); vertices.reserve(length); - for (unsigned i = 0; i < length; i++) { + for (int i = static_cast(length) - 1; i >= 0; --i) { emscripten::val jsPoint = jsArray[i]; // Use property access instead of method calls for better compatibility long x = jsPoint["x"].as(); @@ -211,35 +211,7 @@ EMSCRIPTEN_BINDINGS(libnest2d_js) { std::vector vertices = jsArrayToPointVector(jsVertices); PolygonImpl polygon; polygon.Contour = vertices; - - // Check if we need to reverse the orientation - // For libnest2d with Clipper, we want the area to be positive - double area = sl::area(polygon); - std::cerr << "[DEBUG] Initial polygon area: " << area << std::endl; - - if (area < 0) { - std::cerr << "[DEBUG] Area is negative, reversing vertex order" << std::endl; - std::reverse(vertices.begin(), vertices.end()); - polygon.Contour = vertices; - - // Verify the area is now positive - double newArea = sl::area(polygon); - std::cerr << "[DEBUG] Area after reversal: " << newArea << std::endl; - - for (size_t i = 0; i < vertices.size(); ++i) { - std::cerr << "[DEBUG] Fixed Vertex " << i << ": (" << getX(vertices[i]) << ", " << getY(vertices[i]) << ")" << std::endl; - } - } else { - std::cerr << "[DEBUG] Area is already positive, no reversal needed" << std::endl; - } - - Item item(polygon); - - std::cerr << "[DEBUG] Created item - area: " << item.area() - << ", vertexCount: " << item.vertexCount() - << ", binId: " << item.binId() << std::endl; - - return item; + return Item(polygon); })) .function("binId", select_overload(&Item::binId)) .function("setBinId", select_overload(&Item::binId)) From 8ca5a0493e02f511ad4123d6e5371a949f1b4cee Mon Sep 17 00:00:00 2001 From: "c.lamboo" Date: Fri, 19 Sep 2025 10:15:27 +0200 Subject: [PATCH 3/4] Add tests --- libnest2d_js/libnest2d_js.cpp | 35 ++++++++++++++++++++++++++++++++++ tests/test.cpp | 36 +++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/libnest2d_js/libnest2d_js.cpp b/libnest2d_js/libnest2d_js.cpp index cd047d85..ea47f4f1 100644 --- a/libnest2d_js/libnest2d_js.cpp +++ b/libnest2d_js/libnest2d_js.cpp @@ -35,6 +35,39 @@ EMSCRIPTEN_DECLARE_VAL_TYPE(ItemList); EMSCRIPTEN_DECLARE_VAL_TYPE(DoubleList); EMSCRIPTEN_DECLARE_VAL_TYPE(ResultAndItem); +void testFunction() { + std::vector input; + + auto volume = libnest2d::Box(1000, 1000); + + std::vector items; + + items.emplace_back(libnest2d::Item({ + Point(5, 10), + Point(10, 10), + Point(0, 0) + })); + auto& long_thin_triangle = items.back(); + + items.emplace_back(libnest2d::Item({ + Point(0, 10), + Point(10, 10), + Point(10, 0), + Point(0, 0), + })); + auto& square = items.back(); + + items.emplace_back(libnest2d::Item({ + Point(5, 10), + Point(10, 0), + Point(0, 0) + })); + auto& equilateral_triangle = items.back(); + + auto num_bins = libnest2d::nest(items, volume); + std::cout << "Number of bins used: " << num_bins << std::endl; +} + // Helper function to convert a Point to a JavaScript object emscripten::val pointToJSObject(const Point& point) { emscripten::val obj = emscripten::val::object(); @@ -254,6 +287,8 @@ EMSCRIPTEN_BINDINGS(libnest2d_js) { // Main nest function function("nest", &nestWrapper); + + function("testFunction", &testFunction); } #endif // LIBNEST2D_JS_H diff --git a/tests/test.cpp b/tests/test.cpp index bbc4af8f..dfafaefa 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -1097,3 +1097,39 @@ TEST_CASE("MinAreaBBWithRotatingCalipers", "[Geometry]") { REQUIRE(succ); } } + +TEST_CASE("SimpleNesting", "[Nesting]") { + std::vector input; + + auto volume = libnest2d::Box(1000, 1000); + + std::vector items; + + items.emplace_back(libnest2d::Item({ + Point(5, 10), + Point(10, 10), + Point(0, 0) + })); + auto& long_thin_triangle = items.back(); + + items.emplace_back(libnest2d::Item({ + Point(0, 10), + Point(10, 10), + Point(10, 0), + Point(0, 0), + })); + auto& square = items.back(); + + items.emplace_back(libnest2d::Item({ + Point(5, 10), + Point(10, 0), + Point(0, 0) + })); + auto& equilateral_triangle = items.back(); + + auto num_bins = libnest2d::nest(items, volume); + REQUIRE(num_bins == 1u); + REQUIRE(long_thin_triangle.binId() != libnest2d::BIN_ID_UNSET); + REQUIRE(square.binId() != libnest2d::BIN_ID_UNSET); + REQUIRE(equilateral_triangle.binId() != libnest2d::BIN_ID_UNSET); +} From cce211bcdcf70d7f1df23fd82491cdaec64bc9bd Mon Sep 17 00:00:00 2001 From: "saumya.jain" Date: Fri, 19 Sep 2025 10:25:25 +0200 Subject: [PATCH 4/4] Fix vertex iteration in JS bindings to use forward loop for improved clarity --- libnest2d_js/libnest2d_js.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnest2d_js/libnest2d_js.cpp b/libnest2d_js/libnest2d_js.cpp index cd047d85..684be4be 100644 --- a/libnest2d_js/libnest2d_js.cpp +++ b/libnest2d_js/libnest2d_js.cpp @@ -63,7 +63,7 @@ std::vector jsArrayToPointVector(const emscripten::val& jsArray) { unsigned length = jsArray["length"].as(); vertices.reserve(length); - for (int i = static_cast(length) - 1; i >= 0; --i) { + for (unsigned i = 0; i < length; i++) { emscripten::val jsPoint = jsArray[i]; // Use property access instead of method calls for better compatibility long x = jsPoint["x"].as();