diff --git a/src/libslic3r/CadDocument.cpp b/src/libslic3r/CadDocument.cpp index f7b7e965ca..41ca73b12f 100644 --- a/src/libslic3r/CadDocument.cpp +++ b/src/libslic3r/CadDocument.cpp @@ -2273,7 +2273,10 @@ void CadDocument::apply_feature(TopoDS_Shape& result, bool& have_body, if (f.rib_sketch_ref < 0 || f.rib_sketch_ref >= (int)features.size()) throw std::runtime_error("rib: bad sketch ref"); const CadFeature& sk = features[f.rib_sketch_ref]; - if (sk.type != CadFeatureType::Sketch) + // Project counts as sketch-like here exactly as it does for Extrude, SurfaceExtrude + // and SurfaceRevolve: it carries plane + Line entities, which is all a rib reads. + // Ribbing along a projected body edge is otherwise unreachable. + if (sk.type != CadFeatureType::Sketch && sk.type != CadFeatureType::Project) throw std::runtime_error("rib: ref is not a sketch"); if (f.rib_entity < 0 || f.rib_entity >= (int)sk.entities.size()) throw std::runtime_error("rib: bad entity"); diff --git a/src/slic3r/GUI/DesignPanel.cpp b/src/slic3r/GUI/DesignPanel.cpp index b5a9eae5a0..b9e40fe808 100644 --- a/src/slic3r/GUI/DesignPanel.cpp +++ b/src/slic3r/GUI/DesignPanel.cpp @@ -596,7 +596,10 @@ DesignPanel::DesignPanel(wxWindow* parent) for (int i = 0; i < int(m_doc.features.size()); ++i) { // 3-arg Append: ComboBox's own Append(text, bitmap) hides // wxItemContainer's (text, void*) — see the Sweep picker. - if (m_doc.features[i].type == CadFeatureType::Sketch) + // Project features too: they carry Line entities the kernel ribs from + // just like a drawn sketch, so a projected body edge is a valid path. + if (m_doc.features[i].type == CadFeatureType::Sketch || + m_doc.features[i].type == CadFeatureType::Project) m_rib_sketch->Append(wxString::FromUTF8(m_doc.features[i].name), wxNullBitmap, reinterpret_cast(intptr_t(i))); } diff --git a/tests/libslic3r/test_caddocument.cpp b/tests/libslic3r/test_caddocument.cpp index 8db9ad5a24..428a33bcd3 100644 --- a/tests/libslic3r/test_caddocument.cpp +++ b/tests/libslic3r/test_caddocument.cpp @@ -4048,6 +4048,30 @@ TEST_CASE("rib adds material to a box", "[CadDocument][rib]") REQUIRE_FALSE(bad.recompute()); } +TEST_CASE("rib accepts a Project feature as its sketch ref", "[CadDocument][rib]") +{ + // Project carries plane + Line entities, which is all a rib reads. Every other consumer + // (Extrude, SurfaceExtrude, SurfaceRevolve) already accepts it; Rib used to reject it, + // which made "project a body edge, then rib along it" unreachable. + CadDocument doc; + int sk = doc.add_sketch(SketchShape::Rectangle, SketchPlane::XY(), 40, 40, 10, "Box"); + doc.add_extrude(sk, 10.0, false, BooleanMode::New, "Extrude"); + REQUIRE(doc.recompute()); + double Vbox = double(doc.display_mesh.volume()); + + // Project the whole body onto XY: the 4 top and 4 bottom edges survive as Lines. + int proj = doc.add_project_edges(0, {}, -1, SketchPlane::XY(), "Proj"); + REQUIRE(proj >= 0); + REQUIRE(doc.recompute()); + REQUIRE(doc.features[proj].entities.size() == 8); + + int fi = doc.add_rib(proj, 0, 3.0, 12.0, 0, "RibFromProjection"); + REQUIRE(fi >= 0); + REQUIRE(doc.recompute()); + REQUIRE(doc.error.empty()); + REQUIRE(double(doc.display_mesh.volume()) > Vbox); +} + TEST_CASE("rib non-line entity rejected safely", "[CadDocument][rib]") {