mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-11 02:57:39 +00:00
[CLI]: Fix Plate Config Reading and BuildVolume Height Checks (#15479)
* Fix incorrect early exit for CLI mode no-support preventing parameters from being read * Use PartPlate's m_height to allow CLI to perform proper BuildVolume check * Add safeguard against extruder_pintable_heights and extruder_areas vector size mismatch * Preserve printable_height precision in PartPlate/PartPlateList * Fixed multiple BuildVolume warning issue, and keep check_outside diff minimal
This commit is contained in:
@@ -5199,7 +5199,8 @@ int CLI::run(int argc, char **argv)
|
|||||||
|
|
||||||
Vec3d wipe_tower_size = cur_plate->estimate_wipe_tower_size(m_print_config, w, v, new_extruder_count, filaments_cnt, false, enable_wrapping);
|
Vec3d wipe_tower_size = cur_plate->estimate_wipe_tower_size(m_print_config, w, v, new_extruder_count, filaments_cnt, false, enable_wrapping);
|
||||||
Vec3d plate_origin = cur_plate->get_origin();
|
Vec3d plate_origin = cur_plate->get_origin();
|
||||||
int plate_width, plate_depth, plate_height;
|
int plate_width, plate_depth;
|
||||||
|
double plate_height;
|
||||||
partplate_list.get_plate_size(plate_width, plate_depth, plate_height);
|
partplate_list.get_plate_size(plate_width, plate_depth, plate_height);
|
||||||
float depth = wipe_tower_size(1);
|
float depth = wipe_tower_size(1);
|
||||||
float margin = 15.f, wp_brim_width = 0.f;
|
float margin = 15.f, wp_brim_width = 0.f;
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ BuildVolume::BuildVolume(const std::vector<Vec2d> &printable_area, const double
|
|||||||
: m_bed_shape(printable_area), m_max_print_height(printable_height), m_extruder_shapes(extruder_areas), m_extruder_printable_height(extruder_printable_heights)
|
: m_bed_shape(printable_area), m_max_print_height(printable_height), m_extruder_shapes(extruder_areas), m_extruder_printable_height(extruder_printable_heights)
|
||||||
{
|
{
|
||||||
assert(printable_height >= 0);
|
assert(printable_height >= 0);
|
||||||
//assert(extruder_printable_heights.size() == extruder_areas.size());
|
|
||||||
|
|
||||||
m_polygon = Polygon::new_scale(printable_area);
|
m_polygon = Polygon::new_scale(printable_area);
|
||||||
assert(m_polygon.is_counter_clockwise());
|
assert(m_polygon.is_counter_clockwise());
|
||||||
@@ -86,6 +85,9 @@ BuildVolume::BuildVolume(const std::vector<Vec2d> &printable_area, const double
|
|||||||
m_shared_volume.data[2] = m_bboxf.max.x();
|
m_shared_volume.data[2] = m_bboxf.max.x();
|
||||||
m_shared_volume.data[3] = m_bboxf.max.y();
|
m_shared_volume.data[3] = m_bboxf.max.y();
|
||||||
m_shared_volume.zs[1] = m_bboxf.max.z();
|
m_shared_volume.zs[1] = m_bboxf.max.z();
|
||||||
|
if (extruder_printable_heights.size() < m_extruder_shapes.size())
|
||||||
|
BOOST_LOG_TRIVIAL(warning) << boost::format("extruder_printable_height has only %1% entries but extruder_printable_area has %2%, falling back to the bed printable_height for the missing ones")
|
||||||
|
% extruder_printable_heights.size() % m_extruder_shapes.size();
|
||||||
for (unsigned int index = 0; index < m_extruder_shapes.size(); index++)
|
for (unsigned int index = 0; index < m_extruder_shapes.size(); index++)
|
||||||
{
|
{
|
||||||
std::vector<Vec2d>& extruder_shape = m_extruder_shapes[index];
|
std::vector<Vec2d>& extruder_shape = m_extruder_shapes[index];
|
||||||
@@ -100,7 +102,9 @@ BuildVolume::BuildVolume(const std::vector<Vec2d> &printable_area, const double
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((extruder_shape == printable_area)&&(extruder_printable_heights[index] == printable_height)) {
|
const double extruder_height = index < extruder_printable_heights.size() ? extruder_printable_heights[index] : printable_height;
|
||||||
|
|
||||||
|
if ((extruder_shape == printable_area)&&(extruder_height == printable_height)) {
|
||||||
extruder_volume.same_with_bed = true;
|
extruder_volume.same_with_bed = true;
|
||||||
extruder_volume.type = m_type;
|
extruder_volume.type = m_type;
|
||||||
extruder_volume.bbox = m_bbox;
|
extruder_volume.bbox = m_bbox;
|
||||||
@@ -113,7 +117,7 @@ BuildVolume::BuildVolume(const std::vector<Vec2d> &printable_area, const double
|
|||||||
double poly_area = poly.area();
|
double poly_area = poly.area();
|
||||||
extruder_volume.bbox = get_extents(poly);
|
extruder_volume.bbox = get_extents(poly);
|
||||||
BoundingBoxf temp_bboxf = get_extents(extruder_shape);
|
BoundingBoxf temp_bboxf = get_extents(extruder_shape);
|
||||||
extruder_volume.bboxf = BoundingBoxf3{ to_3d(temp_bboxf.min, 0.), to_3d(temp_bboxf.max, extruder_printable_heights[index]) };
|
extruder_volume.bboxf = BoundingBoxf3{ to_3d(temp_bboxf.min, 0.), to_3d(temp_bboxf.max, extruder_height) };
|
||||||
|
|
||||||
if (extruder_shape.size() >= 4 && std::abs((poly_area - double(extruder_volume.bbox.size().x()) * double(extruder_volume.bbox.size().y()))) < sqr(SCALED_EPSILON))
|
if (extruder_shape.size() >= 4 && std::abs((poly_area - double(extruder_volume.bbox.size().x()) * double(extruder_volume.bbox.size().y()))) < sqr(SCALED_EPSILON))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ PartPlate::PartPlate()
|
|||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
PartPlate::PartPlate(PartPlateList *partplate_list, Vec3d origin, int width, int depth, int height, Plater* platerObj, Model* modelObj, bool printable, PrinterTechnology tech)
|
PartPlate::PartPlate(PartPlateList *partplate_list, Vec3d origin, int width, int depth, double height, Plater* platerObj, Model* modelObj, bool printable, PrinterTechnology tech)
|
||||||
:m_partplate_list(partplate_list), m_plater(platerObj), m_model(modelObj), printer_technology(tech), m_origin(origin), m_width(width), m_depth(depth), m_height(height), m_printable(printable)
|
:m_partplate_list(partplate_list), m_plater(platerObj), m_model(modelObj), printer_technology(tech), m_origin(origin), m_width(width), m_depth(depth), m_height(height), m_printable(printable)
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
@@ -1757,26 +1757,25 @@ std::vector<int> PartPlate::get_extruders_under_cli(bool conside_custom_gcode, D
|
|||||||
else
|
else
|
||||||
obj_support = glb_support;
|
obj_support = glb_support;
|
||||||
|
|
||||||
if (!obj_support)
|
if (obj_support) {
|
||||||
continue;
|
int obj_support_intf_extr = 0;
|
||||||
|
const ConfigOption* support_intf_extr_opt = object->config.option("support_interface_filament");
|
||||||
|
if (support_intf_extr_opt != nullptr)
|
||||||
|
obj_support_intf_extr = support_intf_extr_opt->getInt();
|
||||||
|
if (obj_support_intf_extr != 0)
|
||||||
|
plate_extruders.push_back(obj_support_intf_extr);
|
||||||
|
else if (glb_support_intf_extr != 0)
|
||||||
|
plate_extruders.push_back(glb_support_intf_extr);
|
||||||
|
|
||||||
int obj_support_intf_extr = 0;
|
int obj_support_extr = 0;
|
||||||
const ConfigOption* support_intf_extr_opt = object->config.option("support_interface_filament");
|
const ConfigOption* support_extr_opt = object->config.option("support_filament");
|
||||||
if (support_intf_extr_opt != nullptr)
|
if (support_extr_opt != nullptr)
|
||||||
obj_support_intf_extr = support_intf_extr_opt->getInt();
|
obj_support_extr = support_extr_opt->getInt();
|
||||||
if (obj_support_intf_extr != 0)
|
if (obj_support_extr != 0)
|
||||||
plate_extruders.push_back(obj_support_intf_extr);
|
plate_extruders.push_back(obj_support_extr);
|
||||||
else if (glb_support_intf_extr != 0)
|
else if (glb_support_extr != 0)
|
||||||
plate_extruders.push_back(glb_support_intf_extr);
|
plate_extruders.push_back(glb_support_extr);
|
||||||
|
}
|
||||||
int obj_support_extr = 0;
|
|
||||||
const ConfigOption* support_extr_opt = object->config.option("support_filament");
|
|
||||||
if (support_extr_opt != nullptr)
|
|
||||||
obj_support_extr = support_extr_opt->getInt();
|
|
||||||
if (obj_support_extr != 0)
|
|
||||||
plate_extruders.push_back(obj_support_extr);
|
|
||||||
else if (glb_support_extr != 0)
|
|
||||||
plate_extruders.push_back(glb_support_extr);
|
|
||||||
|
|
||||||
int obj_outer_wall_extr = 0;
|
int obj_outer_wall_extr = 0;
|
||||||
if (const ConfigOption* wall_opt = object->config.option("outer_wall_filament_id"); wall_opt != nullptr)
|
if (const ConfigOption* wall_opt = object->config.option("outer_wall_filament_id"); wall_opt != nullptr)
|
||||||
@@ -2473,7 +2472,7 @@ void PartPlate::clear(bool clear_sliced_result)
|
|||||||
|
|
||||||
/* size and position related functions*/
|
/* size and position related functions*/
|
||||||
//set position and size
|
//set position and size
|
||||||
void PartPlate::set_pos_and_size(Vec3d& origin, int width, int depth, int height, bool with_instance_move, bool do_clear)
|
void PartPlate::set_pos_and_size(Vec3d& origin, int width, int depth, double height, bool with_instance_move, bool do_clear)
|
||||||
{
|
{
|
||||||
bool size_changed = false; //size changed means the machine changed
|
bool size_changed = false; //size changed means the machine changed
|
||||||
bool pos_changed = false;
|
bool pos_changed = false;
|
||||||
@@ -2772,10 +2771,10 @@ bool PartPlate::check_outside(int obj_id, int instance_id, BoundingBoxf3* boundi
|
|||||||
|
|
||||||
if (instance_box.min.z() < SINKING_Z_THRESHOLD) {
|
if (instance_box.min.z() < SINKING_Z_THRESHOLD) {
|
||||||
// Orca: For sinking object, we use a more expensive algorithm so part below build plate won't be considered
|
// Orca: For sinking object, we use a more expensive algorithm so part below build plate won't be considered
|
||||||
// m_plater is null in CLI mode.
|
// m_height mirrors the printer's printable height and is set in CLI mode too, unlike m_plater.
|
||||||
if (m_plater && plate_box.intersects(instance_box)) {
|
if (plate_box.intersects(instance_box)) {
|
||||||
// TODO: FIXME: this does not take exclusion area into account
|
// TODO: FIXME: this does not take exclusion area into account
|
||||||
const BuildVolume build_volume(get_shape(), m_plater->build_volume().printable_height(), m_extruder_areas, m_extruder_heights);
|
const BuildVolume build_volume(get_shape(), m_height, m_extruder_areas, m_extruder_heights);
|
||||||
const auto state = instance->calc_print_volume_state(build_volume);
|
const auto state = instance->calc_print_volume_state(build_volume);
|
||||||
outside = state == ModelInstancePVS_Partly_Outside;
|
outside = state == ModelInstancePVS_Partly_Outside;
|
||||||
}
|
}
|
||||||
@@ -4099,7 +4098,7 @@ void PartPlate::on_filament_deleted(int filament_count, int filament_id)
|
|||||||
|
|
||||||
|
|
||||||
/* PartPlate List related functions*/
|
/* PartPlate List related functions*/
|
||||||
PartPlateList::PartPlateList(int width, int depth, int height, Plater* platerObj, Model* modelObj, PrinterTechnology tech)
|
PartPlateList::PartPlateList(int width, int depth, double height, Plater* platerObj, Model* modelObj, PrinterTechnology tech)
|
||||||
:m_plate_width(width), m_plate_depth(depth), m_plate_height(height), m_plater(platerObj), m_model(modelObj), printer_technology(tech),
|
:m_plate_width(width), m_plate_depth(depth), m_plate_height(height), m_plater(platerObj), m_model(modelObj), printer_technology(tech),
|
||||||
unprintable_plate(this, Vec3d(0.0 + width * (1. + LOGICAL_PART_PLATE_GAP), 0.0, 0.0), width, depth, height, platerObj, modelObj, false, tech)
|
unprintable_plate(this, Vec3d(0.0 + width * (1. + LOGICAL_PART_PLATE_GAP), 0.0, 0.0), width, depth, height, platerObj, modelObj, false, tech)
|
||||||
{
|
{
|
||||||
@@ -4544,7 +4543,7 @@ void PartPlateList::set_default_wipe_tower_pos_for_plate(int plate_idx, bool ini
|
|||||||
}
|
}
|
||||||
|
|
||||||
//this may be happened after machine changed
|
//this may be happened after machine changed
|
||||||
void PartPlateList::reset_size(int width, int depth, int height, bool reload_objects, bool update_shapes)
|
void PartPlateList::reset_size(int width, int depth, double height, bool reload_objects, bool update_shapes)
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(":before size: plate_width %1%, plate_depth %2%, plate_height %3%") % m_plate_width % m_plate_depth % m_plate_height;
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(":before size: plate_width %1%, plate_depth %2%, plate_height %3%") % m_plate_width % m_plate_depth % m_plate_height;
|
||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(":after size: plate_width %1%, plate_depth %2%, plate_height %3%") % width % depth % height;
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(":after size: plate_width %1%, plate_depth %2%, plate_height %3%") % width % depth % height;
|
||||||
@@ -6699,7 +6698,7 @@ int PartPlateList::load_gcode_files()
|
|||||||
//BoundingBoxf3 print_volume = m_plate_list[i]->get_bounding_box(false);
|
//BoundingBoxf3 print_volume = m_plate_list[i]->get_bounding_box(false);
|
||||||
//print_volume.max(2) = this->m_plate_height;
|
//print_volume.max(2) = this->m_plate_height;
|
||||||
//print_volume.min(2) = -1e10;
|
//print_volume.min(2) = -1e10;
|
||||||
m_model->update_print_volume_state({m_plate_list[i]->get_shape(), (double)this->m_plate_height, m_plate_list[i]->get_extruder_areas(), m_plate_list[i]->get_extruder_heights() });
|
m_model->update_print_volume_state({m_plate_list[i]->get_shape(), this->m_plate_height, m_plate_list[i]->get_extruder_areas(), m_plate_list[i]->get_extruder_heights() });
|
||||||
|
|
||||||
if (!m_plate_list[i]->load_gcode_from_file(m_plate_list[i]->m_gcode_path_from_3mf))
|
if (!m_plate_list[i]->load_gcode_from_file(m_plate_list[i]->m_gcode_path_from_3mf))
|
||||||
ret ++;
|
ret ++;
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ private:
|
|||||||
Vec3d m_origin;
|
Vec3d m_origin;
|
||||||
int m_width;
|
int m_width;
|
||||||
int m_depth;
|
int m_depth;
|
||||||
int m_height;
|
double m_height;
|
||||||
float m_height_to_lid;
|
float m_height_to_lid;
|
||||||
float m_height_to_rod;
|
float m_height_to_rod;
|
||||||
bool m_printable;
|
bool m_printable;
|
||||||
@@ -227,7 +227,7 @@ public:
|
|||||||
static void load_render_colors();
|
static void load_render_colors();
|
||||||
|
|
||||||
PartPlate();
|
PartPlate();
|
||||||
PartPlate(PartPlateList *partplate_list, Vec3d origin, int width, int depth, int height, Plater* platerObj, Model* modelObj, bool printable=true, PrinterTechnology tech = ptFFF);
|
PartPlate(PartPlateList *partplate_list, Vec3d origin, int width, int depth, double height, Plater* platerObj, Model* modelObj, bool printable=true, PrinterTechnology tech = ptFFF);
|
||||||
~PartPlate();
|
~PartPlate();
|
||||||
|
|
||||||
bool operator<(PartPlate&) const;
|
bool operator<(PartPlate&) const;
|
||||||
@@ -328,7 +328,7 @@ public:
|
|||||||
Vec3d get_center_origin();
|
Vec3d get_center_origin();
|
||||||
/* size and position related functions*/
|
/* size and position related functions*/
|
||||||
//set position and size
|
//set position and size
|
||||||
void set_pos_and_size(Vec3d& origin, int width, int depth, int height, bool with_instance_move, bool do_clear = true);
|
void set_pos_and_size(Vec3d& origin, int width, int depth, double height, bool with_instance_move, bool do_clear = true);
|
||||||
|
|
||||||
// BBS
|
// BBS
|
||||||
Vec2d get_size() const { return Vec2d(m_width, m_depth); }
|
Vec2d get_size() const { return Vec2d(m_width, m_depth); }
|
||||||
@@ -590,7 +590,7 @@ class PartPlateList : public ObjectBase
|
|||||||
|
|
||||||
int m_plate_width;
|
int m_plate_width;
|
||||||
int m_plate_depth;
|
int m_plate_depth;
|
||||||
int m_plate_height;
|
double m_plate_height;
|
||||||
|
|
||||||
float m_height_to_lid;
|
float m_height_to_lid;
|
||||||
float m_height_to_rod;
|
float m_height_to_rod;
|
||||||
@@ -698,12 +698,12 @@ public:
|
|||||||
static bool is_load_cali_texture;
|
static bool is_load_cali_texture;
|
||||||
static bool is_load_extruder_only_area_textures;
|
static bool is_load_extruder_only_area_textures;
|
||||||
|
|
||||||
PartPlateList(int width, int depth, int height, Plater* platerObj, Model* modelObj, PrinterTechnology tech = ptFFF);
|
PartPlateList(int width, int depth, double height, Plater* platerObj, Model* modelObj, PrinterTechnology tech = ptFFF);
|
||||||
PartPlateList(Plater* platerObj, Model* modelObj, PrinterTechnology tech = ptFFF);
|
PartPlateList(Plater* platerObj, Model* modelObj, PrinterTechnology tech = ptFFF);
|
||||||
~PartPlateList();
|
~PartPlateList();
|
||||||
|
|
||||||
//this may be happened after machine changed
|
//this may be happened after machine changed
|
||||||
void reset_size(int width, int depth, int height, bool reload_objects = true, bool update_shapes = false);
|
void reset_size(int width, int depth, double height, bool reload_objects = true, bool update_shapes = false);
|
||||||
//clear all the instances in the plate, but keep the plates
|
//clear all the instances in the plate, but keep the plates
|
||||||
void clear(bool delete_plates = false, bool release_print_list = false, bool except_locked = false, int plate_index = -1);
|
void clear(bool delete_plates = false, bool release_print_list = false, bool except_locked = false, int plate_index = -1);
|
||||||
//clear all the instances in the plate, and delete the plates, only keep the first default plate
|
//clear all the instances in the plate, and delete the plates, only keep the first default plate
|
||||||
@@ -717,7 +717,7 @@ public:
|
|||||||
//get the plate stride
|
//get the plate stride
|
||||||
double plate_stride_x();
|
double plate_stride_x();
|
||||||
double plate_stride_y();
|
double plate_stride_y();
|
||||||
void get_plate_size(int& width, int& depth, int& height) {
|
void get_plate_size(int& width, int& depth, double& height) {
|
||||||
width = m_plate_width;
|
width = m_plate_width;
|
||||||
depth = m_plate_depth;
|
depth = m_plate_depth;
|
||||||
height = m_plate_height;
|
height = m_plate_height;
|
||||||
|
|||||||
@@ -8278,7 +8278,8 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
|||||||
bool dlg_cont = true;
|
bool dlg_cont = true;
|
||||||
bool is_user_cancel = false;
|
bool is_user_cancel = false;
|
||||||
bool translate_old = false;
|
bool translate_old = false;
|
||||||
int current_width = 0, current_depth = 0, current_height = 0, project_filament_count = 1;
|
int current_width = 0, current_depth = 0, project_filament_count = 1;
|
||||||
|
double current_height = 0;
|
||||||
|
|
||||||
if (input_files.empty())
|
if (input_files.empty())
|
||||||
return std::vector<size_t>();
|
return std::vector<size_t>();
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ add_executable(${_TEST_NAME}_tests
|
|||||||
test_arachne_walls.cpp
|
test_arachne_walls.cpp
|
||||||
test_arrange.cpp
|
test_arrange.cpp
|
||||||
test_bambu_networking.cpp
|
test_bambu_networking.cpp
|
||||||
|
test_buildvolume.cpp
|
||||||
test_calib.cpp
|
test_calib.cpp
|
||||||
test_clipper_offset.cpp
|
test_clipper_offset.cpp
|
||||||
test_clipper_utils.cpp
|
test_clipper_utils.cpp
|
||||||
|
|||||||
40
tests/libslic3r/test_buildvolume.cpp
Normal file
40
tests/libslic3r/test_buildvolume.cpp
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#include <catch2/catch_all.hpp>
|
||||||
|
|
||||||
|
#include "libslic3r/BuildVolume.hpp"
|
||||||
|
|
||||||
|
using namespace Slic3r;
|
||||||
|
|
||||||
|
static std::vector<Vec2d> rect_area(double w, double d)
|
||||||
|
{
|
||||||
|
return { { 0., 0. }, { w, 0. }, { w, d }, { 0., d } };
|
||||||
|
}
|
||||||
|
|
||||||
|
// extruder_printable_height and extruder_printable_area are independent config options, so a
|
||||||
|
// profile can leave the heights short. BuildVolume must not index past the end of the heights.
|
||||||
|
TEST_CASE("BuildVolume falls back to the bed height when extruder_printable_height is short", "[BuildVolume]")
|
||||||
|
{
|
||||||
|
const std::vector<Vec2d> bed = rect_area(200., 200.);
|
||||||
|
const std::vector<std::vector<Vec2d>> areas = { rect_area(200., 200.), rect_area(100., 200.) };
|
||||||
|
const std::vector<double> heights = { 180. };
|
||||||
|
|
||||||
|
const BuildVolume build_volume(bed, 250., areas, heights);
|
||||||
|
|
||||||
|
REQUIRE(build_volume.get_extruder_area_count() == 2);
|
||||||
|
// The extruder with a height of its own keeps it, and differs from the bed, so it gets its own volume.
|
||||||
|
CHECK_THAT(build_volume.get_extruder_area_volume(0).bboxf.max.z(), Catch::Matchers::WithinAbs(180., 1e-6));
|
||||||
|
// The extruder without one falls back to the bed's printable_height instead of reading out of range.
|
||||||
|
CHECK_THAT(build_volume.get_extruder_area_volume(1).bboxf.max.z(), Catch::Matchers::WithinAbs(250., 1e-6));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("BuildVolume keeps per-extruder heights when both vectors match", "[BuildVolume]")
|
||||||
|
{
|
||||||
|
const std::vector<Vec2d> bed = rect_area(200., 200.);
|
||||||
|
const std::vector<std::vector<Vec2d>> areas = { rect_area(120., 200.), rect_area(100., 200.) };
|
||||||
|
const std::vector<double> heights = { 180., 200.5 };
|
||||||
|
|
||||||
|
const BuildVolume build_volume(bed, 250., areas, heights);
|
||||||
|
|
||||||
|
REQUIRE(build_volume.get_extruder_area_count() == 2);
|
||||||
|
CHECK_THAT(build_volume.get_extruder_area_volume(0).bboxf.max.z(), Catch::Matchers::WithinAbs(180., 1e-6));
|
||||||
|
CHECK_THAT(build_volume.get_extruder_area_volume(1).bboxf.max.z(), Catch::Matchers::WithinAbs(200.5, 1e-6));
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user