From 480db09283a96cb75846157222aad22eb59b3893 Mon Sep 17 00:00:00 2001 From: supermerill Date: Fri, 5 Jan 2024 14:15:16 +0100 Subject: [PATCH 01/25] fix filament cooling description crash when no fan is enabled supermerill/SuperSlicer#4047 --- src/slic3r/GUI/PresetHints.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/PresetHints.cpp b/src/slic3r/GUI/PresetHints.cpp index cb549477076..4ae6d925924 100644 --- a/src/slic3r/GUI/PresetHints.cpp +++ b/src/slic3r/GUI/PresetHints.cpp @@ -170,9 +170,10 @@ std::string PresetHints::cooling_description(const Preset &preset_fil, const Pre surface_list += ","; surface_list += _L("Perimeter overhangs"); } - - out += format_wxstr(_L("but for %1% where the speed-up phase is skipped."), surface_list.substr(1)); - has_disable = true; + if (surface_list.size() > 2) { + out += format_wxstr(_L("but for %1% where the speed-up phase is skipped."), surface_list.substr(1)); + has_disable = true; + } } if(has_disable) out += "."; From cf2bf8c4a395abbd62df31048a166cbb1709f9e3 Mon Sep 17 00:00:00 2001 From: supermerill Date: Fri, 5 Jan 2024 15:10:18 +0100 Subject: [PATCH 02/25] fix tip of day moving you to setting tab supermerill/SuperSlicer#4055 --- resources/data/hints.ini | 10 +++++----- src/libslic3r/Preset.cpp | 14 ++++++++++++++ src/libslic3r/Preset.hpp | 1 + src/slic3r/GUI/HintNotification.cpp | 3 ++- 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/resources/data/hints.ini b/resources/data/hints.ini index b0bced57b98..dcfa7fbf34b 100644 --- a/resources/data/hints.ini +++ b/resources/data/hints.ini @@ -21,7 +21,7 @@ # Settings highlight (like search feature) # hypertext_type = settings # hypertext_settings_opt = name_of_settings (hover over settings value and copy last line of hover text) -# hypertext_settings_type = 1 (1 - 5 according to settings tab - to be channged to name of tabs instead of numbers) +# hypertext_settings_type = print ( {print, filament, sla_print, sla_material, printer} according to settings tab) # hypertext_settings_category = Infill (name of panel - written on left in settings) # # Plater top toolbar highlight @@ -67,7 +67,7 @@ text = Fuzzy skin\nDid you know that you can create rough fibre-like texture on the sides of your models using theFuzzy skinfeature? You can also use modifiers to apply fuzzy-skin only to a portion of your model. hypertext_type = settings hypertext_settings_opt = fuzzy_skin -hypertext_settings_type = 1 +hypertext_settings_type = print hypertext_settings_category = Layers and perimeters disabled_tags = SLA @@ -118,7 +118,7 @@ text = Set number of instances\nDid you know that you can right-click a model an text = Combine infill\nDid you know that you can print the infill with a higher layer height compared to perimeters to save print time using the settingCombine infill every. hypertext_type = settings hypertext_settings_opt = infill_every_layers -hypertext_settings_type = 1 +hypertext_settings_type = print hypertext_settings_category = Infill disabled_tags = SLA; simple @@ -142,7 +142,7 @@ disabled_tags = SLA text = Solid infill threshold area\nDid you know that you can make parts of your model with a small cross-section be filled with solid infill automatically? Set theSolid infill threshold area. (Expert mode only.) hypertext_type = settings hypertext_settings_opt = solid_infill_below_area -hypertext_settings_type = 1 +hypertext_settings_type = print hypertext_settings_category = Infill enabled_tags = FFF; expert @@ -207,7 +207,7 @@ hypertext_menubar_item_name = &Configuration Snapshots text = Minimum shell thickness\nDid you know that instead of the number of top and bottom layers, you can define theMinimum shell thicknessin millimeters? This feature is especially useful when using the variable layer height function. hypertext_type = settings hypertext_settings_opt = top_solid_min_thickness -hypertext_settings_type = 1 +hypertext_settings_type = print hypertext_settings_category = Layers and perimeters disabled_tags = SLA diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index c2a68acdca5..52a0c4e872e 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -1743,6 +1743,20 @@ std::string Preset::type_name(Type t) { } } +Preset::Type Preset::type_from_name(std::string name) { + if ("print" == name) + return Preset::TYPE_FFF_PRINT; + if ("filament" == name) + return Preset::TYPE_FFF_FILAMENT; + if ("sla_print" == name) + return Preset::TYPE_SLA_PRINT; + if ("sla_material" == name) + return Preset::TYPE_SLA_MATERIAL; + if ("printer" == name) + return Preset::TYPE_PRINTER; + return Preset::TYPE_INVALID; +} + std::string PresetCollection::section_name() const { return Preset::type_name(this->type()); diff --git a/src/libslic3r/Preset.hpp b/src/libslic3r/Preset.hpp index d70fa6c3474..f4a07870889 100644 --- a/src/libslic3r/Preset.hpp +++ b/src/libslic3r/Preset.hpp @@ -142,6 +142,7 @@ class Preset return PrinterTechnology::ptUnknown; } static std::string type_name(Type t); + static Type type_from_name(std::string name); Type type = TYPE_INVALID; diff --git a/src/slic3r/GUI/HintNotification.cpp b/src/slic3r/GUI/HintNotification.cpp index dbedd0ac632..5d5ada87604 100644 --- a/src/slic3r/GUI/HintNotification.cpp +++ b/src/slic3r/GUI/HintNotification.cpp @@ -415,7 +415,8 @@ void HintDatabase::load_hints_from_file(const boost::filesystem::path& path) // highlight settings } else if (dict["hypertext_type"] == "settings") { std::string opt = dict["hypertext_settings_opt"]; - Preset::Type type = static_cast(std::atoi(dict["hypertext_settings_type"].c_str())); + Preset::Type type = static_cast(Preset::type_from_name(dict["hypertext_settings_type"])); + assert(type != Preset::Type::TYPE_INVALID && wxGetApp().get_tab(type) != nullptr); std::wstring category = boost::nowide::widen(dict["hypertext_settings_category"]); HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, true, documentation_link, [opt, type, category]() { GUI::wxGetApp().sidebar().jump_to_option(opt, type, category); } }; m_loaded_hints.emplace_back(hint_data); From d065f52f95e37326ab1c4eaf7d6a766d820749ea Mon Sep 17 00:00:00 2001 From: supermerill Date: Mon, 8 Jan 2024 04:44:08 +0100 Subject: [PATCH 03/25] fix save .3mf with pattern modifier supermerill/SuperSlicer#3549 --- src/libslic3r/Format/3mf.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index aa9e27e37ab..d827cdab641 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -2934,7 +2934,7 @@ namespace Slic3r { } } else { std::string value = config.opt_serialize(opt_key); - if (!value.empty()) { + if (!value.empty() || opt_key.find("_pattern") == std::string::npos) { pt::ptree& opt_tree = range_tree.add("option", value); opt_tree.put(".opt_key", opt_key); } else { @@ -3160,7 +3160,7 @@ namespace Slic3r { } else { for (const std::string& key : obj->config.keys()) { std::string value = obj->config.opt_serialize(key); - if (!value.empty()) { + if (!value.empty() || key.find("_pattern") == std::string::npos) { stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << OBJECT_TYPE << "\" " << KEY_ATTR << "=\"" << key << "\" " << VALUE_ATTR << "=\"" << value << "\"/>\n"; } else { std::ofstream log("ERROR_FILE_TO_SEND_TO_MERILL_PLZZZZ.txt", std::ios_base::app); @@ -3268,7 +3268,7 @@ namespace Slic3r { for (const std::string& key : volume->config.keys()) { //stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << key << "\" " << VALUE_ATTR << "=\"" << volume->config.opt_serialize(key) << "\"/>\n"; std::string value = volume->config.opt_serialize(key); - if (!value.empty() && key.find("pattern") == std::string::npos) { + if (!value.empty() || key.find("_pattern") == std::string::npos) { stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << key << "\" " << VALUE_ATTR << "=\"" << value << "\"/>\n"; } else { std::ofstream log("ERROR_FILE_TO_SEND_TO_MERILL_PLZZZZ.txt", std::ios_base::app); From 226e7ec52d590ec0644d52ad8e9e0d32928d8459 Mon Sep 17 00:00:00 2001 From: supermerill Date: Mon, 8 Jan 2024 15:04:40 +0100 Subject: [PATCH 04/25] fix crash on one-laye object (doubleslider) fix af9a6c2c1680398ecbdfb18851fcaa74e8e71723 that was fixing 81bbbd17673369cc339b757b1581475005da2ede --- src/slic3r/GUI/DoubleSlider.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/slic3r/GUI/DoubleSlider.cpp b/src/slic3r/GUI/DoubleSlider.cpp index 8c9aa40cc18..87d29b3c201 100644 --- a/src/slic3r/GUI/DoubleSlider.cpp +++ b/src/slic3r/GUI/DoubleSlider.cpp @@ -1098,6 +1098,10 @@ void Control::Ruler::update(wxWindow* win, const std::vector& values, do { if (values.empty()) return; + if (values.size() < 2) { + long_step = -1.0; + return; + } int DPI = GUI::get_dpi_for_window(win); int pixels_per_sm = lround((double)(DPI) * 5.0/25.4); From fd948b58c76360b95877aafb754386891c3431dd Mon Sep 17 00:00:00 2001 From: supermerill Date: Mon, 8 Jan 2024 17:22:31 +0100 Subject: [PATCH 05/25] typo in gui settings --- resources/ui_layout/default/print.ui | 2 +- src/libslic3r/PrintConfig.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/ui_layout/default/print.ui b/resources/ui_layout/default/print.ui index 3fb60dcb189..b07794e5d28 100644 --- a/resources/ui_layout/default/print.ui +++ b/resources/ui_layout/default/print.ui @@ -204,7 +204,7 @@ group:sidetext_width$5:Infill angle end_line line:Modifiers setting:label_width$6:width$5:label$increment:fill_angle_increment - setting:label_width$6:width$5:label$increment:fill_angle_cross + setting:width$5:fill_angle_cross vector_line:fill_angle_template # setting:fill_angle_template group:sidetext_width$5:Advanced diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index b917eb1269d..03f7c2cc152 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2293,7 +2293,7 @@ void PrintConfigDef::init_fff_params() def = this->add("fill_angle_cross", coBool); def->label = L("Alternate Fill Angle"); def->category = OptionCategory::infill; - def->tooltip = L("It's better for some infill like rectilinear to rotate 90° each layer. If this settign is deactivated, they won't do that anymore."); + def->tooltip = L("It's better for some infill like rectilinear to rotate 90° each layer. If this setting is deactivated, they won't do that anymore."); def->mode = comAdvancedE | comSuSi; def->set_default_value(new ConfigOptionBool(true)); @@ -4246,7 +4246,7 @@ void PrintConfigDef::init_fff_params() def->category = OptionCategory::customgcode; def->tooltip = L("If you want to process the output G-code through custom scripts, " "just list their absolute paths here." - "\nSeparate multiple scripts with a semicolon or a line return.\n!! please use '\;' here if you want a not-line-separation ';'!!" + "\nSeparate multiple scripts with a semicolon or a line return.\n!! please use '\\;' here if you want a not-line-separation ';'!!" "\nScripts will be passed the absolute path to the G-code file as the first argument, " "and they can access the Slic3r config settings by reading environment variables." "\nThe script, if passed as a relative path, will also be searched from the slic3r directory, " From 12fbdcd0755bf9aa5d4f993500df35b52eca5508 Mon Sep 17 00:00:00 2001 From: supermerill Date: Mon, 8 Jan 2024 19:04:49 +0100 Subject: [PATCH 06/25] Fix reverse order for perimeters (also for first layer with brim) --- src/libslic3r/ExtrusionEntityCollection.hpp | 5 + src/libslic3r/PerimeterGenerator.cpp | 129 +++++++++----------- src/libslic3r/Print.cpp | 16 +-- src/libslic3r/PrintObject.cpp | 10 +- src/libslic3r/ShortestPath.cpp | 2 +- 5 files changed, 73 insertions(+), 89 deletions(-) diff --git a/src/libslic3r/ExtrusionEntityCollection.hpp b/src/libslic3r/ExtrusionEntityCollection.hpp index 336859cd1cf..3618c0d33de 100644 --- a/src/libslic3r/ExtrusionEntityCollection.hpp +++ b/src/libslic3r/ExtrusionEntityCollection.hpp @@ -52,6 +52,11 @@ class ExtrusionEntityCollection : public ExtrusionEntity return *this; } ~ExtrusionEntityCollection() override { clear(); } + // move all entitites from src into this + void append_move_from(ExtrusionEntityCollection &src) { + m_entities.insert(m_entities.end(), src.m_entities.begin(), src.m_entities.end()); + src.m_entities.clear(); + } /// Operator to convert and flatten this collection to a single vector of ExtrusionPaths. explicit operator ExtrusionPaths() const; diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index 9a4a7318e77..ba6dc540789 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -38,6 +38,25 @@ #endif namespace Slic3r { + +//struct CollectionSimplifyVisitor : public ExtrusionVisitor +//{ +// ExtrusionEntityCollection *previous = nullptr; +// virtual void default_use(ExtrusionEntity& entity) override {}; +// virtual void use(ExtrusionEntityCollection &coll) override +// { +// if (previous && coll.entities().size() == 1) { +// previous->append_move_from(coll); +// } else { +// ExtrusionEntityCollection *old_previous = previous; +// previous = &coll; +// for (size_t i = 0; i < coll.entities().size(); ++i) { coll.set_entities()[i]->visit(*this); } +// previous = old_previous; +// } +// } +//}; + + PerimeterGeneratorLoops get_all_Childs(PerimeterGeneratorLoop loop) { PerimeterGeneratorLoops ret; for (PerimeterGeneratorLoop &child : loop.children) { @@ -348,8 +367,12 @@ ProcessSurfaceResult PerimeterGenerator::process_arachne(int& loop_number, const std::unordered_map map_extrusion_to_idx; for (size_t idx = 0; idx < all_extrusions.size(); idx++) map_extrusion_to_idx.emplace(all_extrusions[idx], idx); - - auto extrusions_constrains = Arachne::WallToolPaths::getRegionOrder(all_extrusions, this->config->external_perimeters_first); + + //TODO: order extrusion for contour/hole separatly + bool reverse_order = this->config->external_perimeters_first + || (this->object_config->brim_width.value > 0 && this->layer->id() == 0) + || (this->object_config->brim_width_interior.value > 0 && this->layer->id() == 0); + auto extrusions_constrains = Arachne::WallToolPaths::getRegionOrder(all_extrusions, reverse_order); for (auto [before, after] : extrusions_constrains) { auto after_it = map_extrusion_to_idx.find(after); ++blocked[after_it->second]; @@ -1598,6 +1621,19 @@ ProcessSurfaceResult PerimeterGenerator::process_classic(int& loop_number, const #if _DEBUG peri_entities.visit(LoopAssertVisitor{}); #endif + // remove the un-needed top collection if only one child. + //peri_entities.visit(CollectionSimplifyVisitor{}); + if (peri_entities.entities().size() == 1) { + if (ExtrusionEntityCollection *coll_child = dynamic_cast( + peri_entities.set_entities().front()); + coll_child != nullptr) { + peri_entities.set_can_sort_reverse(coll_child->can_sort(), coll_child->can_reverse()); + peri_entities.append_move_from(*coll_child); + peri_entities.remove(0); + } + } + + //{ // static int aodfjiaqsdz = 0; // std::stringstream stri; @@ -1613,69 +1649,6 @@ ProcessSurfaceResult PerimeterGenerator::process_classic(int& loop_number, const // svg.Close(); //} - - // if brim will be printed, reverse the order of perimeters so that - // we continue inwards after having finished the brim - // be careful to not print thin walls before perimeters (gapfill will be added after so don't worry for them) - // TODO: add test for perimeter order - const bool brim_first_layer = this->layer->id() == 0 && (this->object_config->brim_width.value > 0 || this->object_config->brim_width_interior.value > 0); - if (this->config->external_perimeters_first || brim_first_layer) { - if (this->config->external_perimeters_nothole.value || brim_first_layer) { - if (this->config->external_perimeters_hole.value || brim_first_layer) { - //reverse only not-thin wall - ExtrusionEntityCollection coll2; - for (const ExtrusionEntity* loop : peri_entities.entities()) { - if ( (loop->is_loop() && loop->role() != erThinWall)) { - coll2.append(*loop); - } - } - coll2.reverse(); - for (const ExtrusionEntity* loop : peri_entities.entities()) { - if (!((loop->is_loop() && loop->role() != erThinWall))) { - coll2.append(*loop); - } - } - //note: this hacky thing is possible because coll2.entities contains in fact peri_entities's entities - //if you does peri_entities = coll2, you'll delete peri_entities's entities() and then you have nothing. - peri_entities = std::move(coll2); - } else { - //reverse only not-hole perimeters - ExtrusionEntityCollection coll2; - for (const ExtrusionEntity* loop : peri_entities.entities()) { - if ((loop->is_loop() && loop->role() != erThinWall) && !(((ExtrusionLoop*)loop)->loop_role() & ExtrusionLoopRole::elrHole) != 0) { - coll2.append(*loop); - } - } - coll2.reverse(); - for (const ExtrusionEntity* loop : peri_entities.entities()) { - if (!((loop->is_loop() && loop->role() != erThinWall) && !(((ExtrusionLoop*)loop)->loop_role() & ExtrusionLoopRole::elrHole) != 0)) { - coll2.append(*loop); - } - } - //note: this hacky thing is possible because coll2.entities contains in fact entities's entities - //if you does peri_entities = coll2, you'll delete peri_entities's entities and then you have nothing. - peri_entities = std::move(coll2); - } - } else if (this->config->external_perimeters_hole.value) { - //reverse the hole, and put them in first place. - ExtrusionEntityCollection coll2; - for (const ExtrusionEntity* loop : peri_entities.entities()) { - if ((loop->is_loop() && loop->role() != erThinWall) && (((ExtrusionLoop*)loop)->loop_role() & ExtrusionLoopRole::elrHole) != 0) { - coll2.append(*loop); - } - } - coll2.reverse(); - for (const ExtrusionEntity* loop : peri_entities.entities()) { - if (!((loop->is_loop() && loop->role() != erThinWall) && (((ExtrusionLoop*)loop)->loop_role() & ExtrusionLoopRole::elrHole) != 0)) { - coll2.append(*loop); - } - } - //note: this hacky thing is possible because coll2.entities contains in fact peri_entities's entities - //if you does peri_entities = coll2, you'll delete peri_entities's entities and then you have nothing. - peri_entities = std::move(coll2); - } - - } // append perimeters for this slice as a collection if (!peri_entities.empty()) { //move it, to avoid to clone evrything and then delete it @@ -2651,6 +2624,13 @@ ExtrusionEntityCollection PerimeterGenerator::_traverse_loops( if (idx.first >= loops.size()) better_chain.push_back(idx); } + + // if brim will be printed, reverse the order of perimeters so that + // we continue inwards after having finished the brim + const bool reverse_contour = (this->layer->id() == 0 && this->object_config->brim_width.value > 0) || + (this->config->external_perimeters_first.value && this->config->external_perimeters_nothole.value); + const bool reverse_hole = (this->layer->id() == 0 && this->object_config->brim_width_interior.value > 0) || + (this->config->external_perimeters_first.value && this->config->external_perimeters_hole.value); //move from coll to coll_out and getting children of each in the same time. (deep first) for (const std::pair &idx : better_chain) { @@ -2691,9 +2671,10 @@ ExtrusionEntityCollection PerimeterGenerator::_traverse_loops( assert(thin_walls.empty()); ExtrusionEntityCollection children = this->_traverse_loops(loop.children, thin_walls, has_overhang ? 1 : count_since_overhang < 0 ? -1 : (count_since_overhang+1)); coll[idx.first] = nullptr; - if (loop.is_contour) { + if ((loop.is_contour && !reverse_contour) || (!loop.is_contour && reverse_hole)) { //note: this->layer->id() % 2 == 1 already taken into account in the is_steep_overhang compute (to save time). - if (loop.is_steep_overhang && this->layer->id() % 2 == 1) + // if contour: reverse if steep_overhang & odd. if hole: the opposite + if ((loop.is_steep_overhang && this->layer->id() % 2 == 1) == loop.is_contour) eloop->make_clockwise(); else eloop->make_counter_clockwise(); @@ -2701,10 +2682,10 @@ ExtrusionEntityCollection PerimeterGenerator::_traverse_loops( if (!children.empty()) { ExtrusionEntityCollection print_child_beforeplz; print_child_beforeplz.set_can_sort_reverse(false, false); - if (children.entities().size() > 1) { + if (children.entities().size() > 1 && (children.can_reverse() || children.can_sort())) { print_child_beforeplz.append(children); } else { - print_child_beforeplz.append(std::move(children.entities())); + print_child_beforeplz.append_move_from(children); } print_child_beforeplz.append(*eloop); coll_out.append(std::move(print_child_beforeplz)); @@ -2712,7 +2693,8 @@ ExtrusionEntityCollection PerimeterGenerator::_traverse_loops( coll_out.append(*eloop); } } else { - if (loop.is_steep_overhang && this->layer->id() % 2 == 1) + // if hole: reverse if steep_overhang & odd. if contour: the opposite + if ((loop.is_steep_overhang && this->layer->id() % 2 == 1) != loop.is_contour) eloop->make_counter_clockwise(); else eloop->make_clockwise(); @@ -2721,10 +2703,10 @@ ExtrusionEntityCollection PerimeterGenerator::_traverse_loops( ExtrusionEntityCollection print_child_beforeplz; print_child_beforeplz.set_can_sort_reverse(false, false); print_child_beforeplz.append(*eloop); - if (children.entities().size() > 1) { + if (children.entities().size() > 1 && (children.can_reverse() || children.can_sort())) { print_child_beforeplz.append(children); } else { - print_child_beforeplz.append(std::move(children.entities())); + print_child_beforeplz.append_move_from(children); } coll_out.append(std::move(print_child_beforeplz)); } else { @@ -2778,7 +2760,7 @@ ExtrusionEntityCollection PerimeterGenerator::_traverse_extrusions(std::vector

size()); for (const Arachne::ExtrusionJunction& ej : extrusion->junctions) { - //remove duplicate poitns from arachne + //remove duplicate points from arachne if(extrusion_path.empty() || (ej.p.x() != extrusion_path.back().x() || ej.p.y() != extrusion_path.back().y())) extrusion_path.emplace_back(ej.p.x(), ej.p.y(), ej.w); @@ -3016,7 +2998,6 @@ void PerimeterGenerator::_merge_thin_walls(ExtrusionEntityCollection &extrusions current_loop = last_loop; } virtual void use(ExtrusionEntityCollection &collection) override { - collection.set_can_sort_reverse(true, true); //for each loop? (or other collections) for (ExtrusionEntity *entity : collection.entities()) entity->visit(*this); diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index ebaf8b197b8..19c1e232561 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -52,7 +52,7 @@ void Print::clear() } // Called by Print::apply(). -// This method only accepts PrintConfig option keys. +// This method only accepts PrintConfig option keys. Not PrintObjectConfig or PrintRegionConfig, go to PrintObject for these bool Print::invalidate_state_by_config_options(const ConfigOptionResolver& /* new_config */, const std::vector &opt_keys) { if (opt_keys.empty()) @@ -67,13 +67,14 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver& /* ne "avoid_crossing_top", "bed_shape", "bed_temperature", - "chamber_temperature", "before_layer_gcode", "between_objects_gcode", "bridge_acceleration", "bridge_internal_acceleration", "bridge_fan_speed", "bridge_internal_fan_speed", + "brim_acceleration", + "chamber_temperature", "colorprint_heights", "complete_objects_sort", "cooling", @@ -230,16 +231,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver& /* ne } else if (steps_ignore.find(opt_key) != steps_ignore.end()) { // These steps have no influence on the G-code whatsoever. Just ignore them. } else if ( - opt_key == "brim_inside_holes" - || opt_key == "brim_width" - || opt_key == "brim_width_interior" - || opt_key == "brim_ears" - || opt_key == "brim_ears_detection_length" - || opt_key == "brim_ears_max_angle" - || opt_key == "brim_ears_pattern" - || opt_key == "brim_per_object" - || opt_key == "brim_separation" - || opt_key == "complete_objects_one_skirt" + opt_key == "complete_objects_one_skirt" || opt_key == "draft_shield" || opt_key == "min_skirt_length" || opt_key == "ooze_prevention" diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index c1f28c9cfe3..abbaa325c4c 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1086,8 +1086,6 @@ bool PrintObject::invalidate_state_by_config_options( invalidated |= m_print->invalidate_step(psGCodeExport); } else if ( opt_key == "brim_inside_holes" - || opt_key == "brim_width" - || opt_key == "brim_width_interior" || opt_key == "brim_ears" || opt_key == "brim_ears_detection_length" || opt_key == "brim_ears_max_angle" @@ -1097,6 +1095,14 @@ bool PrintObject::invalidate_state_by_config_options( invalidated |= m_print->invalidate_step(psSkirtBrim); // Brim is printed below supports, support invalidates brim and skirt. steps.emplace_back(posSupportMaterial); + } else if ( + opt_key == "brim_width" + || opt_key == "brim_width_interior") { + invalidated |= m_print->invalidate_step(psSkirtBrim); + // these two may change the ordering of first layer perimeters + steps.emplace_back(posPerimeters); + // Brim is printed below supports, support invalidates brim and skirt. + steps.emplace_back(posSupportMaterial); } else { // for legacy, if we can't handle this option let's invalidate all steps this->invalidate_all_steps(); diff --git a/src/libslic3r/ShortestPath.cpp b/src/libslic3r/ShortestPath.cpp index d5a9207598e..84f885bc796 100644 --- a/src/libslic3r/ShortestPath.cpp +++ b/src/libslic3r/ShortestPath.cpp @@ -1021,7 +1021,7 @@ std::vector> chain_segments_greedy2(SegmentEndPointFunc std::vector> chain_extrusion_entities(std::vector &entities, const Point *start_near) { auto segment_end_point = [&entities](size_t idx, bool first_point) -> const Point& { return first_point ? entities[idx]->first_point() : entities[idx]->last_point(); }; - auto could_reverse = [&entities](size_t idx) { const ExtrusionEntity *ee = entities[idx]; return ee->is_loop() || ee->can_reverse(); }; + auto could_reverse = [&entities](size_t idx) { const ExtrusionEntity *ee = entities[idx]; return ee->can_reverse(); }; std::vector> out = chain_segments_greedy_constrained_reversals(segment_end_point, could_reverse, entities.size(), start_near); for (std::pair &segment : out) { ExtrusionEntity *ee = entities[segment.first]; From 28f51c318482e80b9fea47ef4763b9e5b3780b19 Mon Sep 17 00:00:00 2001 From: supermerill Date: Tue, 9 Jan 2024 11:53:49 +0100 Subject: [PATCH 07/25] no retract if before_wipe with length 0 --- src/libslic3r/GCodeWriter.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libslic3r/GCodeWriter.cpp b/src/libslic3r/GCodeWriter.cpp index 97eb7ecf31a..9a62c24d46f 100644 --- a/src/libslic3r/GCodeWriter.cpp +++ b/src/libslic3r/GCodeWriter.cpp @@ -636,7 +636,10 @@ std::string GCodeWriter::extrude_to_xyz(const Vec3d &point, double dE, const std std::string GCodeWriter::retract(bool before_wipe) { double factor = before_wipe ? m_tool->retract_before_wipe() : 1.; - assert(factor >= 0. && factor <= 1. + EPSILON); + assert((factor >= 0. || before_wipe) && factor <= 1. + EPSILON); + // if before_wipe but no retract_before_wipe, then no retract + if (factor == 0) + return ""; //check for override if (config_region && config_region->print_retract_length >= 0) { return this->_retract( @@ -646,8 +649,6 @@ std::string GCodeWriter::retract(bool before_wipe) "retract" ); } - auto rect_length = m_tool->retract_length(); - auto rect_length2 = m_tool->retract_restart_extra(); return this->_retract( factor * m_tool->retract_length(), factor * m_tool->retract_restart_extra(), From 3b839f91c8cf2480923de5e62e555c08ef3cd7db Mon Sep 17 00:00:00 2001 From: supermerill Date: Wed, 10 Jan 2024 17:56:15 +0100 Subject: [PATCH 08/25] Fix (half of) unit testing & fix overextrusion from perimeter_overlap if encroachment --- src/CMakeLists.txt | 1 + src/libslic3r/Config.hpp | 4 + src/libslic3r/Extruder.hpp | 2 + src/libslic3r/ExtrusionEntity.cpp | 75 +++- src/libslic3r/ExtrusionEntity.hpp | 5 +- src/libslic3r/Fill/Fill.cpp | 9 +- src/libslic3r/Fill/FillBase.cpp | 12 +- src/libslic3r/Fill/FillBase.hpp | 2 + src/libslic3r/Flow.cpp | 4 +- src/libslic3r/Format/STL.hpp | 1 + src/libslic3r/GCode.cpp | 4 +- src/libslic3r/GCodeWriter.cpp | 4 +- src/libslic3r/PerimeterGenerator.cpp | 46 ++- src/libslic3r/PrintBase.hpp | 10 +- src/libslic3r/PrintConfig.cpp | 1 + src/libslic3r/TriangleMesh.hpp | 3 - src/libslic3r/Utils.hpp | 1 + src/slic3r/GUI/ConfigManipulation.cpp | 6 +- src/test-utils/CMakeLists.txt | 10 + .../ClipboardXX/include/clipboardxx.hpp | 41 +++ .../ClipboardXX/include/detail/exception.hpp | 13 + .../ClipboardXX/include/detail/interface.hpp | 14 + .../ClipboardXX/include/detail/linux.hpp | 30 ++ .../include/detail/linux/provider.hpp | 14 + .../detail/linux/x11_event_handler.hpp | 167 +++++++++ .../include/detail/linux/x11_provider.hpp | 33 ++ .../include/detail/linux/xcb/xcb.hpp | 177 +++++++++ .../include/detail/linux/xcb/xcb_event.hpp | 51 +++ .../ClipboardXX/include/detail/windows.hpp | 110 ++++++ src/test-utils/stl_to_cpp.cpp | 60 ++++ tests/superslicerlibslic3r/CMakeLists.txt | 53 ++- .../test_clipper_utils.cpp | 150 ++++++-- .../test_complete_objects.cpp | 57 +-- tests/superslicerlibslic3r/test_data.cpp | 124 +++---- .../test_dense_infill.cpp | 14 +- .../test_denserinfill.cpp | 71 ++-- .../test_extrusion_entity.cpp | 32 +- tests/superslicerlibslic3r/test_fill.cpp | 287 ++++++++++++--- tests/superslicerlibslic3r/test_flow.cpp | 60 ++-- .../superslicerlibslic3r/test_gcodewriter.cpp | 50 +-- tests/superslicerlibslic3r/test_geometry.cpp | 68 ++-- tests/superslicerlibslic3r/test_model.cpp | 19 +- tests/superslicerlibslic3r/test_print.cpp | 336 +++++++++++++++--- .../superslicerlibslic3r/test_skirt_brim.cpp | 87 ++--- tests/superslicerlibslic3r/test_thin.cpp | 65 ++-- 45 files changed, 1859 insertions(+), 524 deletions(-) create mode 100644 src/test-utils/CMakeLists.txt create mode 100644 src/test-utils/ClipboardXX/include/clipboardxx.hpp create mode 100644 src/test-utils/ClipboardXX/include/detail/exception.hpp create mode 100644 src/test-utils/ClipboardXX/include/detail/interface.hpp create mode 100644 src/test-utils/ClipboardXX/include/detail/linux.hpp create mode 100644 src/test-utils/ClipboardXX/include/detail/linux/provider.hpp create mode 100644 src/test-utils/ClipboardXX/include/detail/linux/x11_event_handler.hpp create mode 100644 src/test-utils/ClipboardXX/include/detail/linux/x11_provider.hpp create mode 100644 src/test-utils/ClipboardXX/include/detail/linux/xcb/xcb.hpp create mode 100644 src/test-utils/ClipboardXX/include/detail/linux/xcb/xcb_event.hpp create mode 100644 src/test-utils/ClipboardXX/include/detail/windows.hpp create mode 100644 src/test-utils/stl_to_cpp.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7b2defea726..90a891c70cc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.13) project(Slic3r-native) add_subdirectory(build-utils) +add_subdirectory(test-utils) add_subdirectory(admesh) add_subdirectory(avrdude) # boost/nowide diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp index e0688b7f850..db381393d4a 100644 --- a/src/libslic3r/Config.hpp +++ b/src/libslic3r/Config.hpp @@ -2321,6 +2321,10 @@ class ConfigBase : public ConfigOptionResolver bool set_deserialize_nothrow(const t_config_option_key &opt_key_src, const std::string &value_src, ConfigSubstitutionContext& substitutions, bool append = false); // May throw BadOptionTypeException() if the operation fails. void set_deserialize(const t_config_option_key &opt_key, const std::string &str, ConfigSubstitutionContext& config_substitutions, bool append = false); + void set_deserialize(const t_config_option_key &opt_key, const std::string &str){ //for tests + ConfigSubstitutionContext no_context(ForwardCompatibilitySubstitutionRule::Disable); + set_deserialize(opt_key, str, no_context); + } void set_deserialize_strict(const t_config_option_key &opt_key, const std::string &str, bool append = false) { ConfigSubstitutionContext ctxt{ ForwardCompatibilitySubstitutionRule::Disable }; this->set_deserialize(opt_key, str, ctxt, append); } struct SetDeserializeItem { diff --git a/src/libslic3r/Extruder.hpp b/src/libslic3r/Extruder.hpp index e4e16d2639e..b3113a04d99 100644 --- a/src/libslic3r/Extruder.hpp +++ b/src/libslic3r/Extruder.hpp @@ -1,6 +1,8 @@ #ifndef slic3r_Extruder_hpp_ #define slic3r_Extruder_hpp_ +#include + #include "libslic3r.h" #include "Point.hpp" diff --git a/src/libslic3r/ExtrusionEntity.cpp b/src/libslic3r/ExtrusionEntity.cpp index 2874cddaa3b..2d610338c42 100644 --- a/src/libslic3r/ExtrusionEntity.cpp +++ b/src/libslic3r/ExtrusionEntity.cpp @@ -378,29 +378,80 @@ ExtrusionRole ExtrusionEntity::string_to_role(const std::string_view role) else return erNone; } + + +std::string role_to_code(ExtrusionRole role) +{ + switch (role) { + case erNone : return L("None"); + case erPerimeter : return L("IPeri"); + case erExternalPerimeter : return L("EPeri"); + case erOverhangPerimeter : return L("OPeri"); + case erInternalInfill : return L("IFill"); + case erSolidInfill : return L("SFill"); + case erTopSolidInfill : return L("TFill"); + case erIroning : return L("Iron"); + case erBridgeInfill : return L("EBridge"); + case erInternalBridgeInfill : return L("IBridge"); + case erThinWall : return L("ThinW"); + case erGapFill : return L("GFill"); + case erSkirt : return L("Skirt"); + case erSupportMaterial : return L("Supp"); + case erSupportMaterialInterface : return L("SuppI"); + case erWipeTower : return L("WTower"); + case erMilling : return L("Mill"); + case erCustom : return L("Custom"); + case erMixed : return L("Mixed"); + case erTravel : return L("Travel"); + default : assert(false); + } + + return ""; +} + + +std::string looprole_to_code(ExtrusionLoopRole looprole) +{ + std::string code; + if(elrDefault == (looprole & elrDefault)) + code += std::string("D"); + if(elrInternal == (looprole & elrInternal)) + code += std::string("Int"); + if(elrSkirt == (looprole & elrSkirt)) + code += std::string("Skirt"); + if(elrHole == (looprole & elrHole)) + code += std::string("Hole"); + if(elrVase == (looprole & elrVase)) + code += std::string("Vase"); + if(elrFirstLoop == (looprole & elrFirstLoop)) + code += std::string("First"); + + return code; +} + void ExtrusionPrinter::use(const ExtrusionPath &path) { - ss << "ExtrusionPath:" << (uint16_t)path.role() << "{"; + ss << (json?"\"":"") << "ExtrusionPath" << (path.can_reverse()?"":"Oriented") << (json?"_":":") << role_to_code(path.role()) << (json?"\":":"") << "["; for (int i = 0; i < path.polyline.size(); i++) { if (i != 0) ss << ","; double x = (mult * (path.polyline.get_points()[i].x())); double y = (mult * (path.polyline.get_points()[i].y())); - ss << std::fixed << "{"<<(trunc?(int)x:x) << "," << (trunc ? (int)y : y) <<"}"; + ss << std::fixed << "["<<(trunc>0?(int(x*trunc))/double(trunc):x) << "," << (trunc>0?(int(y*trunc))/double(trunc):y) <<"]"; } - ss << "}"; + ss << "]"; } void ExtrusionPrinter::use(const ExtrusionPath3D &path3D) { - ss << "ExtrusionPath3D:" << (uint16_t)path3D.role() << "{"; + ss << (json?"\"":"") << "ExtrusionPath3D" << (path3D.can_reverse()?"":"Oriented") << (json?"_":":") << role_to_code(path3D.role()) << (json?"\":":"") << "["; for (int i = 0; i < path3D.polyline.size();i++){ if (i != 0) ss << ","; double x = (mult * (path3D.polyline.get_points()[i].x())); double y = (mult * (path3D.polyline.get_points()[i].y())); double z = (path3D.z_offsets.size() > i ? mult * (path3D.z_offsets[i]) : -1); - ss << std::fixed << "{" << (trunc ? (int)x : x) << "," << (trunc ? (int)y : y) << "," << (trunc ? (int)z : z) << "}"; + ss << std::fixed << "[" << (trunc>0?(int(x*trunc))/double(trunc):x) << "," << (trunc>0?(int(y*trunc))/double(trunc):y) << "," << (trunc>0?(int(z*trunc))/double(trunc):z) << "]"; } - ss << "}"; + ss << "]"; } void ExtrusionPrinter::use(const ExtrusionMultiPath &multipath) { - ss << "ExtrusionMultiPath:" << (uint16_t)multipath.role() << "{"; + ss << (json?"\"":"") << "ExtrusionMultiPath" << (multipath.can_reverse()?"":"Oriented") << (json?"_":":") << role_to_code(multipath.role()) << (json?"\":":"") << "{"; for (int i = 0; i < multipath.paths.size(); i++) { if (i != 0) ss << ","; multipath.paths[i].visit(*this); @@ -408,7 +459,7 @@ void ExtrusionPrinter::use(const ExtrusionMultiPath &multipath) { ss << "}"; } void ExtrusionPrinter::use(const ExtrusionMultiPath3D &multipath3D) { - ss << "multipath3D:" << (uint16_t)multipath3D.role() << "{"; + ss << (json?"\"":"") << "multipath3D" << (multipath3D.can_reverse()?"":"Oriented") << (json?"_":":") << role_to_code(multipath3D.role()) << (json?"\":":"") << "{"; for (int i = 0; i < multipath3D.paths.size(); i++) { if (i != 0) ss << ","; multipath3D.paths[i].visit(*this); @@ -416,7 +467,8 @@ void ExtrusionPrinter::use(const ExtrusionMultiPath3D &multipath3D) { ss << "}"; } void ExtrusionPrinter::use(const ExtrusionLoop &loop) { - ss << "ExtrusionLoop:" << (uint16_t)loop.role()<<":" <<(uint16_t)loop.loop_role()<<"{"; + ss << (json?"\"":"") << "ExtrusionLoop" << (json?"_":":") << role_to_code(loop.role())<<"_" << looprole_to_code(loop.loop_role()) << (json?"\":":"") << "{"; + if(!loop.can_reverse()) ss << (json?"\"":"") << "oriented" << (json?"\":":"=") << "true,"; for (int i = 0; i < loop.paths.size(); i++) { if (i != 0) ss << ","; loop.paths[i].visit(*this); @@ -424,12 +476,13 @@ void ExtrusionPrinter::use(const ExtrusionLoop &loop) { ss << "}"; } void ExtrusionPrinter::use(const ExtrusionEntityCollection &collection) { - ss << "ExtrusionEntityCollection:" << (uint16_t)collection.role() << "{"; + ss << (json?"\"":"") << "ExtrusionEntityCollection" << (json?"_":":") << role_to_code(collection.role()) << (json?"\":":"") << "{"; + if(!collection.can_sort()) ss << (json?"\"":"") << "no_sort" << (json?"\":":"=") << "true,"; + if(!collection.can_reverse()) ss << (json?"\"":"") << "oriented" << (json?"\":":"=") << "true,"; for (int i = 0; i < collection.entities().size(); i++) { if (i != 0) ss << ","; collection.entities()[i]->visit(*this); } - if(!collection.can_sort()) ss<<", no_sort=true"; ss << "}"; } diff --git a/src/libslic3r/ExtrusionEntity.hpp b/src/libslic3r/ExtrusionEntity.hpp index bbc81a65899..6bc37026572 100644 --- a/src/libslic3r/ExtrusionEntity.hpp +++ b/src/libslic3r/ExtrusionEntity.hpp @@ -628,9 +628,10 @@ inline void extrusion_entities_append_loops_and_paths(ExtrusionEntitiesPtr &dst, class ExtrusionPrinter : public ExtrusionVisitorConst { std::stringstream ss; double mult; - bool trunc; + int trunc; + bool json; public: - ExtrusionPrinter(double mult = 0.0001, bool trunc = false) : mult(mult), trunc(trunc) { } + ExtrusionPrinter(double mult = 0.000001, int trunc = 0, bool json = false) : mult(mult), trunc(trunc), json(json) { } virtual void use(const ExtrusionPath& path) override; virtual void use(const ExtrusionPath3D& path3D) override; virtual void use(const ExtrusionMultiPath& multipath) override; diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index 63de0d2d51b..fd6774661a5 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -532,7 +532,14 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive: //give the overlap size to let the infill do his overlap //add overlap if at least one perimeter - const float perimeter_spacing = layerm->flow(frPerimeter).spacing(); + float perimeter_spacing = 0; + if(layerm->region().config().perimeters == 1) + perimeter_spacing = layerm->flow(frExternalPerimeter).spacing(); + else if(layerm->region().config().only_one_perimeter_top) + //note: use the min of the two to avoid overextrusion if only one perimeter top + perimeter_spacing = std::min(layerm->flow(frPerimeter).spacing(), layerm->flow(frExternalPerimeter).spacing()); + else //if(layerm->region().config().perimeters > 1) + perimeter_spacing = layerm->flow(frPerimeter).spacing(); // Used by the concentric infill pattern to clip the loops to create extrusion paths. f->loop_clipping = scale_t(layerm->region().config().get_computed_value("seam_gap", surface_fill.params.extruder - 1) * surface_fill.params.flow.nozzle_diameter()); diff --git a/src/libslic3r/Fill/FillBase.cpp b/src/libslic3r/Fill/FillBase.cpp index 08daf3c2222..5008b80a01d 100644 --- a/src/libslic3r/Fill/FillBase.cpp +++ b/src/libslic3r/Fill/FillBase.cpp @@ -167,17 +167,7 @@ double Fill::compute_unscaled_volume_to_fill(const Surface* surface, const FillP } else { for (const ExPolygon& poly : intersection_ex(ExPolygons{ surface->expolygon }, this->no_overlap_expolygons)) { polyline_volume += params.flow.height() * unscaled(unscaled(poly.area())); - double perimeter_gap_usage = params.config->perimeter_overlap.get_abs_value(1); - // add external "perimeter gap" - //TODO: use filament_max_overlap to reduce it - //double filament_max_overlap = params.config->get_computed_value("filament_max_overlap", params.extruder - 1); - double perimeter_round_gap = unscaled(poly.contour.length()) * params.flow.height() * (1 - 0.25 * PI) * 0.5; - // add holes "perimeter gaps" - double holes_gaps = 0; - for (auto hole = poly.holes.begin(); hole != poly.holes.end(); ++hole) { - holes_gaps += unscaled(hole->length()) * params.flow.height() * (1 - 0.25 * PI) * 0.5; - } - polyline_volume += (perimeter_round_gap + holes_gaps) * perimeter_gap_usage; + //note: the no_overlap_expolygons is already at spacing from the centerline of the perimeter. } } return polyline_volume; diff --git a/src/libslic3r/Fill/FillBase.hpp b/src/libslic3r/Fill/FillBase.hpp index 5dcadea8fc4..83dc11161bf 100644 --- a/src/libslic3r/Fill/FillBase.hpp +++ b/src/libslic3r/Fill/FillBase.hpp @@ -173,6 +173,7 @@ class Fill ExPolygon /* expolygon */, Polylines & /* polylines_out */) const { BOOST_LOG_TRIVIAL(error)<<"Error, the fill isn't implemented"; + assert(false); }; // Used for concentric infill to generate ThickPolylines using Arachne. @@ -182,6 +183,7 @@ class Fill ExPolygon expolygon, ThickPolylines &thick_polylines_out) const { BOOST_LOG_TRIVIAL(error) << "Error, the arachne fill isn't implemented"; + assert(false); }; virtual float _layer_angle(size_t idx) const { return can_angle_cross && (idx & 1) ? float(M_PI/2.) : 0; } diff --git a/src/libslic3r/Flow.cpp b/src/libslic3r/Flow.cpp index 269c1cb3b53..d81be3aeef9 100644 --- a/src/libslic3r/Flow.cpp +++ b/src/libslic3r/Flow.cpp @@ -526,12 +526,12 @@ float Flow::rounded_rectangle_extrusion_spacing(float width, float height, float #endif } -float Flow::rounded_rectangle_extrusion_width_from_spacing(float spacing, float height, float m_spacing_ratio) +float Flow::rounded_rectangle_extrusion_width_from_spacing(float spacing, float height, float spacing_ratio) { #ifdef HAS_PERIMETER_LINE_OVERLAP return (spacing + PERIMETER_LINE_OVERLAP_FACTOR * height * (1. - 0.25 * PI) * spacing_ratio); #else - return float(spacing + height * (1. - 0.25 * PI) * m_spacing_ratio); + return float(spacing + height * (1. - 0.25 * PI) * spacing_ratio); #endif } diff --git a/src/libslic3r/Format/STL.hpp b/src/libslic3r/Format/STL.hpp index cff7dc08696..b2c4345129d 100644 --- a/src/libslic3r/Format/STL.hpp +++ b/src/libslic3r/Format/STL.hpp @@ -5,6 +5,7 @@ namespace Slic3r { class TriangleMesh; class ModelObject; +class Model; // Load an STL file into a provided model. extern bool load_stl(const char *path, Model *model, const char *object_name = nullptr); diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 69545332479..bba0eb5b915 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -3277,7 +3277,7 @@ LayerResult GCode::process_layer( if (this->m_layer != nullptr && this->m_layer->id() == 0) { m_avoid_crossing_perimeters.use_external_mp(true); for (const ExtrusionEntity* ee : print_object->brim().entities()) - gcode += this->extrude_entity(*ee, "brim"); + gcode += this->extrude_entity(*ee, "Brim"); m_avoid_crossing_perimeters.use_external_mp(false); m_avoid_crossing_perimeters.disable_once(); m_last_too_small.polyline.clear(); @@ -3386,7 +3386,7 @@ LayerResult GCode::process_layer( assert(instance_to_print.print_object.brim().entities()[instance_to_print.instance_id]->is_collection()); if (const ExtrusionEntityCollection* coll = dynamic_cast(instance_to_print.print_object.brim().entities()[instance_to_print.instance_id])) { for (const ExtrusionEntity* ee : coll->entities()) - gcode += this->extrude_entity(*ee, "brim"); + gcode += this->extrude_entity(*ee, "Brim"); } m_avoid_crossing_perimeters.use_external_mp(false); m_avoid_crossing_perimeters.disable_once(); diff --git a/src/libslic3r/GCodeWriter.cpp b/src/libslic3r/GCodeWriter.cpp index 9a62c24d46f..b538b58fcc9 100644 --- a/src/libslic3r/GCodeWriter.cpp +++ b/src/libslic3r/GCodeWriter.cpp @@ -433,7 +433,7 @@ std::string GCodeWriter::set_speed(const double speed, const std::string &commen const double F = speed * 60; m_current_speed = speed; assert(F > 0.); - assert(F < 100000.); + assert(F < 10000000.); // GCodeG1Formatter w; // w.emit_f(F); // w.emit_comment(this->config.gcode_comments, comment); @@ -565,7 +565,7 @@ bool GCodeWriter::will_move_z(double z) const we don't perform an actual Z move. */ if (m_lifted > 0) { double nominal_z = m_pos.z() - m_lifted; - if (z >= nominal_z + EPSILON && z <= m_pos.z() - EPSILON) + if (z >= nominal_z - EPSILON && z <= m_pos.z() + EPSILON) return false; } return true; diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index ba6dc540789..5b598e0e015 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -804,7 +804,19 @@ void PerimeterGenerator::process() this->get_ext_perimeter_spacing() / 2 : // two or more loops? this->get_perimeter_spacing() / 2; - infill_peri_overlap = scale_t(this->config->get_abs_value("infill_overlap", unscale(perimeter_spacing + solid_infill_spacing) / 2)); + //infill_peri_overlap = scale_t(this->config->get_abs_value("infill_overlap", unscale(perimeter_spacing + solid_infill_spacing) / 2)); + //give the overlap size to let the infill do his overlap + //add overlap if at least one perimeter + coordf_t perimeter_spacing_for_encroach = 0; + if(this->config->perimeters == 1) + perimeter_spacing_for_encroach = this->ext_perimeter_flow.spacing(); + else if(this->config->only_one_perimeter_top.value) + //note: use the min of the two to avoid overextrusion if only one perimeter top + // TODO: only do that if there is a top & a not-top surface + perimeter_spacing_for_encroach = std::min(this->perimeter_flow.spacing(), this->ext_perimeter_flow.spacing()); + else //if(layerm->region().config().perimeters > 1) + perimeter_spacing_for_encroach = this->perimeter_flow.spacing(); + infill_peri_overlap = scale_t(this->config->get_abs_value("infill_overlap", perimeter_spacing_for_encroach)); } //remove gapfill from last @@ -2609,21 +2621,25 @@ ExtrusionEntityCollection PerimeterGenerator::_traverse_loops( //little check: if you have external holes with only one extrusion and internal things, please draw the internal first, just in case it can help print the hole better. std::vector> better_chain; - for (const std::pair& idx : chain) { - if(idx.first < loops.size()) - if (!loops[idx.first].is_external() || (!loops[idx.first].is_contour && !loops[idx.first].children.empty())) - better_chain.push_back(idx); - } - for (const std::pair& idx : chain) { - if (idx.first < loops.size()) - if (idx.first < loops.size() && loops[idx.first].is_external() && !(!loops[idx.first].is_contour && !loops[idx.first].children.empty())) - better_chain.push_back(idx); - } - //thin walls always last! - for (const std::pair& idx : chain) { - if (idx.first >= loops.size()) - better_chain.push_back(idx); + { + std::vector> alone_holes; + std::vector> keep_ordering; + std::vector> thin_walls; + for (const std::pair &idx : chain) { + if (idx.first < loops.size()) + if (!loops[idx.first].is_external() || + (!loops[idx.first].is_contour && !loops[idx.first].children.empty())) + alone_holes.push_back(idx); + else + keep_ordering.push_back(idx); + else + thin_walls.push_back(idx); + } + append(better_chain, std::move(alone_holes)); + append(better_chain, std::move(keep_ordering)); + append(better_chain, std::move(thin_walls)); } + assert(better_chain.size() == chain.size()); // if brim will be printed, reverse the order of perimeters so that // we continue inwards after having finished the brim diff --git a/src/libslic3r/PrintBase.hpp b/src/libslic3r/PrintBase.hpp index 7b9073f7755..03a89ef7a92 100644 --- a/src/libslic3r/PrintBase.hpp +++ b/src/libslic3r/PrintBase.hpp @@ -463,8 +463,16 @@ class PrintBase : public ObjectBase m_status_callback(SlicingStatus(percent, message, flags)); else m_status_callback(SlicingStatus(percent, message, args, flags)); + } else { + printf("%d => ", percent); + if(args.empty()) + printf(message.c_str()); + else if (args.size()==1) + printf(message.c_str(), args.front().c_str()); + else if (args.size()==2) + printf(message.c_str(), args.front().c_str(), args.back().c_str()); + printf("\n"); } - else printf("%d => %s\n", percent, message.c_str()); } typedef std::function cancel_callback_type; diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 03f7c2cc152..609366e7c21 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -7989,6 +7989,7 @@ std::unordered_set prusa_export_to_remove_keys = { "solid_infill_acceleration", "solid_infill_extrusion_spacing", "solid_infill_fan_speed", +"solid_infill_overlap", "start_gcode_manual", "support_material_angle_height", "support_material_acceleration", diff --git a/src/libslic3r/TriangleMesh.hpp b/src/libslic3r/TriangleMesh.hpp index 533cc12c6a7..4b8563f7eb0 100644 --- a/src/libslic3r/TriangleMesh.hpp +++ b/src/libslic3r/TriangleMesh.hpp @@ -152,9 +152,6 @@ class TriangleMesh const TriangleMeshStats& stats() const { return m_stats; } indexed_triangle_set its; - -/// --- for tests ----- /// - Pointf3s vertices(); private: TriangleMeshStats m_stats; diff --git a/src/libslic3r/Utils.hpp b/src/libslic3r/Utils.hpp index f525c98378d..283010cce32 100644 --- a/src/libslic3r/Utils.hpp +++ b/src/libslic3r/Utils.hpp @@ -8,6 +8,7 @@ #include #include +#include #include "libslic3r.h" diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index aba0b1ef753..5f585fe7ece 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -345,13 +345,13 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config) bool has_spiral_vase = have_perimeters && config->opt_bool("spiral_vase"); - for (auto el : { "external_perimeters_vase", "external_perimeters_nothole", "external_perimeters_hole", "perimeter_bonding"}) - toggle_field(el, config->opt_bool("external_perimeters_first")); - bool have_arachne = have_perimeters && config->opt_enum("perimeter_generator") == PerimeterGeneratorType::Arachne; for (auto el : { "wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle", "wall_distribution_count", "min_feature_size", "min_bead_width", "aaa" }) toggle_field(el, have_arachne); + toggle_field("external_perimeters_vase", config->opt_bool("external_perimeters_first")); + for (auto el : { "external_perimeters_nothole", "external_perimeters_hole", "perimeter_bonding"}) + toggle_field(el, config->opt_bool("external_perimeters_first") && !have_arachne); for (auto el : {"perimeter_loop", "extra_perimeters_overhangs", "no_perimeter_unsupported_algo", "thin_perimeters", "overhangs_reverse", "perimeter_round_corners"}) diff --git a/src/test-utils/CMakeLists.txt b/src/test-utils/CMakeLists.txt new file mode 100644 index 00000000000..713593a9a04 --- /dev/null +++ b/src/test-utils/CMakeLists.txt @@ -0,0 +1,10 @@ +project(test-utils) + +# convert stl to c++ code to inclusion in test +add_executable(stl_to_cpp stl_to_cpp.cpp) + +target_link_libraries(stl_to_cpp libslic3r) + +if (WIN32) + prusaslicer_copy_dlls(stl_to_cpp) +endif() diff --git a/src/test-utils/ClipboardXX/include/clipboardxx.hpp b/src/test-utils/ClipboardXX/include/clipboardxx.hpp new file mode 100644 index 00000000000..03687fe37e1 --- /dev/null +++ b/src/test-utils/ClipboardXX/include/clipboardxx.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include "detail/interface.hpp" +#if defined(_WIN32) || defined(WIN32) + #define WINDOWS + #include "detail/windows.hpp" +#elif defined(__linux__) + #define LINUX + #include "detail/linux.hpp" +#else + #error "platform not supported" +#endif + +#include +#include + +namespace clipboardxx { + +#ifdef WINDOWS +using ClipboardType = ClipboardWindows; +#elif defined(LINUX) +using ClipboardType = ClipboardLinux; +#endif + +class clipboard { +public: + clipboard() : m_clipboard(std::make_unique()) {} + + void operator<<(const std::string &text) const { copy(text); } + + void copy(const std::string &text) const { m_clipboard->copy(text); } + + void operator>>(std::string &result) const { result = paste(); } + + std::string paste() const { return m_clipboard->paste(); } + +private: + std::unique_ptr m_clipboard; +}; + +} // namespace clipboardxx diff --git a/src/test-utils/ClipboardXX/include/detail/exception.hpp b/src/test-utils/ClipboardXX/include/detail/exception.hpp new file mode 100644 index 00000000000..442786891f9 --- /dev/null +++ b/src/test-utils/ClipboardXX/include/detail/exception.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include +#include + +namespace clipboardxx { + +class exception : public std::runtime_error { +public: + exception(const std::string &reason) : std::runtime_error(reason){}; +}; + +} // namespace clipboardxx diff --git a/src/test-utils/ClipboardXX/include/detail/interface.hpp b/src/test-utils/ClipboardXX/include/detail/interface.hpp new file mode 100644 index 00000000000..69d5c4fb185 --- /dev/null +++ b/src/test-utils/ClipboardXX/include/detail/interface.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include + +namespace clipboardxx { + +class ClipboardInterface { +public: + virtual ~ClipboardInterface() = default; + virtual void copy(const std::string &text) const = 0; + virtual std::string paste() const = 0; +}; + +} // namespace clipboardxx diff --git a/src/test-utils/ClipboardXX/include/detail/linux.hpp b/src/test-utils/ClipboardXX/include/detail/linux.hpp new file mode 100644 index 00000000000..34abc7c7b59 --- /dev/null +++ b/src/test-utils/ClipboardXX/include/detail/linux.hpp @@ -0,0 +1,30 @@ +#pragma once + +#ifdef LINUX + #include "exception.hpp" + #include "interface.hpp" + #include "linux/x11_provider.hpp" + +namespace clipboardxx { + +class ClipboardLinux : public ClipboardInterface { +public: + ClipboardLinux() : m_provider(std::make_unique()) {} + + void copy(const std::string &text) const override { + try { + m_provider->copy(text); + } catch (const exception &error) { + throw exception("XCB Error: " + std::string(error.what())); + } + } + + std::string paste() const override { return m_provider->paste(); } + +private: + const std::unique_ptr m_provider; +}; + +} // namespace clipboardxx + +#endif diff --git a/src/test-utils/ClipboardXX/include/detail/linux/provider.hpp b/src/test-utils/ClipboardXX/include/detail/linux/provider.hpp new file mode 100644 index 00000000000..465976792e7 --- /dev/null +++ b/src/test-utils/ClipboardXX/include/detail/linux/provider.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include + +namespace clipboardxx { + +class LinuxClipboardProvider { +public: + virtual void copy(const std::string &text) = 0; + virtual std::string paste() = 0; + virtual ~LinuxClipboardProvider() = default; +}; + +} // namespace clipboardxx diff --git a/src/test-utils/ClipboardXX/include/detail/linux/x11_event_handler.hpp b/src/test-utils/ClipboardXX/include/detail/linux/x11_event_handler.hpp new file mode 100644 index 00000000000..b127148bef4 --- /dev/null +++ b/src/test-utils/ClipboardXX/include/detail/linux/x11_event_handler.hpp @@ -0,0 +1,167 @@ +#pragma once + +#include "xcb/xcb.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace clipboardxx { + +constexpr std::chrono::duration kHandleEventsForEverDelay = std::chrono::milliseconds(20); +constexpr std::chrono::duration kWaitForPasteDataTimeout = std::chrono::milliseconds(300); +constexpr std::array kSupportedTextFormats = { + "UTF8_STRING", "text/plain;charset=utf-8", "text/plain;charset=UTF-8", "GTK_TEXT_BUFFER_CONTENTS", "STRING", "TEXT", + "text/plain"}; + +struct EssentialAtoms { + std::vector supported_text_formats; + xcb::Atom clipboard, targets, atom, buffer; +}; + +class X11EventHandler { +public: + X11EventHandler(std::shared_ptr xcb) + : m_xcb(std::move(xcb)), m_atoms(create_essential_atoms()), + m_targets(generate_targets_atom_array(m_atoms.targets, m_atoms.supported_text_formats)), + m_stop_event_thread(false) { + m_event_thread = std::thread(&X11EventHandler::handle_events_for_ever, this); + } + + ~X11EventHandler() { + m_stop_event_thread = true; + m_event_thread.join(); + } + + void set_copy_data(const std::string &data) { + std::lock_guard lock_guard(m_lock); + m_copy_data = std::optional(data); + } + + std::string get_paste_data() { + { + std::lock_guard lock_guard(m_lock); + if (do_we_own_clipoard()) + return m_copy_data.value(); + else + m_xcb->request_selection_data(m_atoms.clipboard, m_atoms.supported_text_formats.at(0), m_atoms.buffer); + } + + wait_for_paste_data_with_timeout(kWaitForPasteDataTimeout); + std::lock_guard lock_guard(m_lock); + std::string result = m_paste_data.value_or(std::string("")); + m_paste_data.reset(); + return result; + } + +private: + EssentialAtoms create_essential_atoms() const { + EssentialAtoms atoms; + atoms.clipboard = m_xcb->create_atom("CLIPBOARD"); + atoms.buffer = m_xcb->create_atom("BUFFER"); + atoms.targets = m_xcb->create_atom("TARGETS"); + atoms.atom = m_xcb->create_atom("ATOM"); + + atoms.supported_text_formats = std::vector(kSupportedTextFormats.size()); + std::transform(kSupportedTextFormats.begin(), kSupportedTextFormats.end(), atoms.supported_text_formats.begin(), + [this](const char* name) { return m_xcb->create_atom(std::string(name)); }); + return atoms; + } + + std::vector generate_targets_atom_array(xcb::Atom target, const std::vector &atoms) { + std::vector targets(atoms.size() + 1); + targets[0] = target; + std::copy(atoms.begin(), atoms.end(), targets.begin() + 1); + return targets; + } + + bool do_we_own_clipoard() const { return m_copy_data.has_value(); } + + void wait_for_paste_data_with_timeout(std::chrono::milliseconds timeout) { + m_paste_data.reset(); + std::chrono::system_clock::time_point start_time = std::chrono::system_clock::now(); + + while (true) { + if (std::chrono::system_clock::now() - start_time > timeout) + break; + + std::this_thread::sleep_for(std::chrono::milliseconds(kHandleEventsForEverDelay)); + std::lock_guard lock_guard(m_lock); + + if (m_paste_data.has_value()) + break; + } + } + + void handle_events_for_ever() noexcept { + while (true) { + if (m_stop_event_thread) + break; + + std::this_thread::sleep_for(kHandleEventsForEverDelay); + std::lock_guard lock_guard(m_lock); + std::optional> event = m_xcb->get_latest_event(); + + if (event.has_value()) + handle_event(std::move(event.value())); + } + } + + void handle_event(std::unique_ptr event) { + switch (event->get_type()) { + case xcb::Event::Type::kRequestSelection: + handle_request_selection_event(reinterpret_cast(event.get())); + break; + case xcb::Event::Type::kSelectionClear: + m_copy_data = std::nullopt; + break; + case xcb::Event::Type::kSelectionNotify: + handle_selection_notify_event(reinterpret_cast(event.get())); + break; + case xcb::Event::Type::kNone: + return; + } + } + + void handle_request_selection_event(const xcb::RequestSelectionEvent* event) { + if (event->m_selection != m_atoms.clipboard || !m_copy_data.has_value()) + return; + + bool found_format = std::find(m_atoms.supported_text_formats.begin(), m_atoms.supported_text_formats.end(), + event->m_target) != m_atoms.supported_text_formats.end(); + if (event->m_target == m_atoms.targets) { + m_xcb->write_on_window_property(event->m_requestor, event->m_property, m_atoms.atom, m_targets); + m_xcb->notify_window_property_change(event->m_requestor, event->m_property, m_atoms.atom, + event->m_selection); + } else if (found_format) { + m_xcb->write_on_window_property(event->m_requestor, event->m_property, event->m_target, + m_copy_data.value()); + m_xcb->notify_window_property_change(event->m_requestor, event->m_property, event->m_target, + event->m_selection); + } else { + m_xcb->notify_window_property_change(event->m_requestor, 0, event->m_target, event->m_selection); + } + } + + void handle_selection_notify_event(const xcb::SelectionNotifyEvent* event) { + if (event->m_selection != m_atoms.clipboard || m_paste_data.has_value()) + return; + m_paste_data = m_xcb->get_our_property_value(m_atoms.buffer); + } + + const std::shared_ptr m_xcb; + const EssentialAtoms m_atoms; + const std::vector m_targets; + std::optional m_copy_data, m_paste_data; + std::mutex m_lock; + std::thread m_event_thread; + std::atomic m_stop_event_thread; +}; + +} // namespace clipboardxx diff --git a/src/test-utils/ClipboardXX/include/detail/linux/x11_provider.hpp b/src/test-utils/ClipboardXX/include/detail/linux/x11_provider.hpp new file mode 100644 index 00000000000..ebc9da4d0c1 --- /dev/null +++ b/src/test-utils/ClipboardXX/include/detail/linux/x11_provider.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include "../exception.hpp" +#include "provider.hpp" +#include "x11_event_handler.hpp" +#include "xcb/xcb.hpp" + +#include + +namespace clipboardxx { + +constexpr const char* kClipboardAtomName = "CLIPBOARD"; + +class X11Provider : public LinuxClipboardProvider { +public: + X11Provider() + : m_xcb(std::make_shared()), m_clipboard_atom(m_xcb->create_atom(kClipboardAtomName)), + m_event_handler(X11EventHandler(m_xcb)) {} + + void copy(const std::string &text) override { + m_xcb->become_selection_owner(m_clipboard_atom); + m_event_handler.set_copy_data(text); + } + + std::string paste() override { return m_event_handler.get_paste_data(); } + +private: + const std::shared_ptr m_xcb; + const xcb::Xcb::Atom m_clipboard_atom; + X11EventHandler m_event_handler; +}; + +} // namespace clipboardxx diff --git a/src/test-utils/ClipboardXX/include/detail/linux/xcb/xcb.hpp b/src/test-utils/ClipboardXX/include/detail/linux/xcb/xcb.hpp new file mode 100644 index 00000000000..a44bfb8a64f --- /dev/null +++ b/src/test-utils/ClipboardXX/include/detail/linux/xcb/xcb.hpp @@ -0,0 +1,177 @@ +#pragma once + +#include "../../exception.hpp" +#include "xcb_event.hpp" + +#include +#include +#include +#include + +namespace clipboardxx { +namespace xcb { + +constexpr uint8_t kBitsPerByte = 8; +constexpr uint8_t kFilterXcbEventType = 0x80; + +class Xcb { +public: + using Atom = xcb_atom_t; + using Window = xcb_window_t; + + class XcbException : public exception { + public: + XcbException(const std::string &reason, int32_t error_code) + : exception(reason + " (" + std::to_string(error_code) + ")"){}; + }; + + Xcb() : m_conn(create_connection()), m_window(create_window(m_conn.get())) {} + + Atom create_atom(const std::string &name) { + xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_conn.get(), false, name.size(), name.c_str()); + + xcb_generic_error_t* error = nullptr; + std::unique_ptr reply(xcb_intern_atom_reply(m_conn.get(), cookie, &error)); + handle_generic_error(error, "Cannot create atom with name '" + name + "'"); + + return reply->atom; + } + + void become_selection_owner(Atom selection) { + xcb_void_cookie_t cookie = xcb_set_selection_owner_checked(m_conn.get(), m_window, selection, XCB_CURRENT_TIME); + handle_generic_error(xcb_request_check(m_conn.get(), cookie), "Cannot become owner of clipboard selection"); + xcb_flush(m_conn.get()); + } + + std::optional> get_latest_event() { + std::unique_ptr event(xcb_poll_for_event(m_conn.get())); + + // TODO: find a workaround for this + assert(m_conn != nullptr); + + if (!event) + return std::nullopt; + return convert_generic_event_to_event(std::move(event)); + } + + template + void write_on_window_property(Window window, Atom property, Atom target, const Container &data) { + xcb_change_property(m_conn.get(), XCB_PROP_MODE_REPLACE, window, property, target, + sizeof(ValueType) * kBitsPerByte, data.size(), data.data()); + xcb_flush(m_conn.get()); + } + + void notify_window_property_change(Window window, Atom property, Atom target, Atom selection) { + const xcb_selection_notify_event_t event{.response_type = XCB_SELECTION_NOTIFY, + .pad0 = 0, + .sequence = 0, + .time = XCB_CURRENT_TIME, + .requestor = window, + .selection = selection, + .target = target, + .property = property}; + + xcb_send_event(m_conn.get(), false, window, XCB_EVENT_MASK_PROPERTY_CHANGE, + reinterpret_cast(&event)); + xcb_flush(m_conn.get()); + } + + void request_selection_data(Atom selection, Atom target, Atom result) { + xcb_convert_selection_checked(m_conn.get(), m_window, selection, target, result, XCB_CURRENT_TIME); + xcb_flush(m_conn.get()); + } + + std::string get_our_property_value(Atom property) { + xcb_get_property_cookie_t cookie = + xcb_get_property(m_conn.get(), static_cast(true), m_window, property, XCB_ATOM_ANY, 0, -1); + + xcb_generic_error_t* error = nullptr; + std::unique_ptr reply(xcb_get_property_reply(m_conn.get(), cookie, &error)); + std::unique_ptr error_ptr(error); + if (error != nullptr) + return std::string(""); + + const char* data = reinterpret_cast(xcb_get_property_value(reply.get())); + uint32_t length = xcb_get_property_value_length(reply.get()); + return std::string(data, length); + } + +private: + class XcbConnectionDeleter { + public: + void operator()(xcb_connection_t* conn) { xcb_disconnect(conn); } + }; + + using XcbConnectionPtr = std::unique_ptr; + + XcbConnectionPtr create_connection() const { + XcbConnectionPtr connection(xcb_connect(nullptr, nullptr)); + int32_t error = xcb_connection_has_error(connection.get()); + if (error > 0) + throw XcbException("Cannot connect to X server", error); + + return connection; + } + + xcb_window_t create_window(xcb_connection_t* conn) const { + xcb_screen_t* screen = get_root_screen(conn); + xcb_window_t window = xcb_generate_id(conn); + + uint32_t mask_value = XCB_EVENT_MASK_PROPERTY_CHANGE; + xcb_void_cookie_t cookie = xcb_create_window_checked(conn, XCB_COPY_FROM_PARENT, window, screen->root, 0, 0, 1, + 1, 0, XCB_WINDOW_CLASS_COPY_FROM_PARENT, + screen->root_visual, XCB_CW_EVENT_MASK, &mask_value); + handle_generic_error(xcb_request_check(conn, cookie), "Cannot create window"); + + return window; + } + + xcb_screen_t* get_root_screen(xcb_connection_t* conn) const { + const xcb_setup_t* setup_info = xcb_get_setup(conn); + xcb_screen_iterator_t screens = xcb_setup_roots_iterator(setup_info); + return screens.data; + } + + void handle_generic_error(xcb_generic_error_t* error, const std::string &error_msg) const { + std::unique_ptr error_ptr(error); + if (error_ptr) + throw XcbException(error_msg, error_ptr->error_code); + } + + std::unique_ptr convert_generic_event_to_event(std::unique_ptr event) { + uint8_t event_type = event->response_type & ~kFilterXcbEventType; + switch (event_type) { + // someone requested clipboard data + case XCB_SELECTION_REQUEST: { + xcb_selection_request_event_t* sel_request_event = + reinterpret_cast(event.get()); + return std::make_unique(sel_request_event->requestor, sel_request_event->owner, + sel_request_event->selection, sel_request_event->target, + sel_request_event->property); + } + + // we are no longer owner of clipboard + case XCB_SELECTION_CLEAR: { + xcb_selection_clear_event_t* sel_clear_event = reinterpret_cast(event.get()); + return std::make_unique(sel_clear_event->selection); + } + + // our selection has been changed + case XCB_SELECTION_NOTIFY: { + xcb_selection_notify_event_t* sel_notify_event = + reinterpret_cast(event.get()); + return std::make_unique(sel_notify_event->requestor, sel_notify_event->selection, + sel_notify_event->target, sel_notify_event->property); + } + + default: + return std::make_unique(Event::Type::kNone); + } + } + + const XcbConnectionPtr m_conn; + const xcb_window_t m_window; +}; + +} // namespace xcb +} // namespace clipboardxx diff --git a/src/test-utils/ClipboardXX/include/detail/linux/xcb/xcb_event.hpp b/src/test-utils/ClipboardXX/include/detail/linux/xcb/xcb_event.hpp new file mode 100644 index 00000000000..694b234d71b --- /dev/null +++ b/src/test-utils/ClipboardXX/include/detail/linux/xcb/xcb_event.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include + +namespace clipboardxx { +namespace xcb { + +using Atom = xcb_atom_t; +using Window = xcb_window_t; + +class Event { +public: + enum Type { kNone = 0, kRequestSelection, kSelectionClear, kSelectionNotify }; + + Event(Type type) : m_type(type) {} + + Type get_type() const { return m_type; } + +private: + Type m_type; +}; + +class RequestSelectionEvent : public Event { +public: + RequestSelectionEvent(Window requestor, Window owner, Atom selection, Atom target, Atom property) + : Event(Type::kRequestSelection), m_requestor(requestor), m_owner(owner), m_selection(selection), + m_target(target), m_property(property) {} + + const Window m_requestor, m_owner; + const Atom m_selection, m_target, m_property; +}; + +class SelectionNotifyEvent : public Event { +public: + SelectionNotifyEvent(Window requestor, Atom selection, Atom target, Atom property) + : Event(Type::kSelectionNotify), m_requestor(requestor), m_selection(selection), m_target(target), + m_property(property) {} + + const Window m_requestor; + const Atom m_selection, m_target, m_property; +}; + +class SelectionClearEvent : public Event { +public: + SelectionClearEvent(Atom selection) : Event(Type::kSelectionClear), m_selection(selection) {} + + const Atom m_selection; +}; + +} // namespace xcb +} // namespace clipboardxx diff --git a/src/test-utils/ClipboardXX/include/detail/windows.hpp b/src/test-utils/ClipboardXX/include/detail/windows.hpp new file mode 100644 index 00000000000..c2f7e3d18ed --- /dev/null +++ b/src/test-utils/ClipboardXX/include/detail/windows.hpp @@ -0,0 +1,110 @@ +#pragma once + +#include "exception.hpp" +#include "interface.hpp" + +#include +#include + +#ifdef WINDOWS + #include + +namespace clipboardxx { + +class ClipboardWindows : public ClipboardInterface { +public: + void copy(const std::string &text) const override { + OpenCloseClipboardRaii clipboard_raii; + + empty_clipboard(); + std::unique_ptr buffer = allocate_memory_with_size(text.size() + 1); + write_string_to_memory_null_terminated(text, buffer.get()); + set_clipboard_data_from_memory(std::move(buffer)); + } + + std::string paste() const noexcept override { + OpenCloseClipboardRaii clipboard_raii; + return get_clipboard_data(); + } + +private: + class OpenCloseClipboardRaii { + public: + OpenCloseClipboardRaii() { + if (!OpenClipboard(0)) + throw WindowsException("Cannot open clipboard"); + } + + ~OpenCloseClipboardRaii() { CloseClipboard(); } + }; + + class WindowsException : public exception { + public: + WindowsException(const std::string &reason) : exception(reason + " (" + get_last_windows_error() + ")"){}; + + private: + std::string get_last_windows_error() const { + DWORD error = GetLastError(); + if (error) { + LPVOID buffer = nullptr; + DWORD buffer_len = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast(&buffer), 0, nullptr); + + if (buffer_len) { + LPTSTR buffer_char = reinterpret_cast(buffer); + std::string result(buffer_char, buffer_char + buffer_len); + LocalFree(buffer); + return result; + } + } + + return std::string("unknown windows error"); + } + }; + + class WindowsPtrDeleter { + public: + void operator()(char* ptr) { GlobalFree(ptr); } + }; + + void empty_clipboard() const { + BOOL succeed = EmptyClipboard(); + if (!succeed) + throw WindowsException("Cannot empty clipboard"); + } + + std::unique_ptr allocate_memory_with_size(size_t size) const { + std::unique_ptr global( + reinterpret_cast(GlobalAlloc(GMEM_FIXED, sizeof(char) * size))); + if (!global) + throw WindowsException("Cannot allocate memory for copying text"); + + return global; + } + + void write_string_to_memory_null_terminated(const std::string &text, char* memory) const { + std::copy(text.begin(), text.end(), memory); + memory[text.size()] = '\0'; + } + + void set_clipboard_data_from_memory(std::unique_ptr buffer) const { + if (SetClipboardData(CF_TEXT, buffer.get())) { + // from now on the system owns the buffer + buffer.release(); + } else { + throw WindowsException("Cannot set clipboard data"); + } + } + + std::string get_clipboard_data() const { + char* result = reinterpret_cast(GetClipboardData(CF_TEXT)); + if (!result) + return std::string(""); + return std::string(result); + } +}; + +} // namespace clipboardxx + +#endif diff --git a/src/test-utils/stl_to_cpp.cpp b/src/test-utils/stl_to_cpp.cpp new file mode 100644 index 00000000000..a896d47f4c3 --- /dev/null +++ b/src/test-utils/stl_to_cpp.cpp @@ -0,0 +1,60 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ClipboardXX/include/clipboardxx.hpp" + +int main(int argc, char const *argv[]) +{ + if (argc != 2) { + std::cout<<"usage: stl_to_cpp \"path/to/stl.stl\"\n"; + return 0; + } + std::string path_str = argv[1]; + if(path_str.front() == '\"' && path_str.back() == '\"') + path_str = path_str.substr(1,path_str.size()-2); + Slic3r::Model model; + bool result = load_stl(path_str.c_str(), &model, "obj"); + if (!result) { + std::cout << "error, can't read '" << path_str << "'\n"; + return 0; + } + clipboardxx::clipboard clipboard; + //TriangleMesh tm2 = TriangleMesh(std::vector{{-5, -5, -0.1}},std::vector{{1,4,3}}); + std::stringstream out_cpp; + int idx_obj = 0; + for (Slic3r::ModelObject* obj : model.objects) { + int idx_vol = 0; + for(Slic3r::ModelVolume *vol : obj->volumes) { + Slic3r::TriangleMesh mesh = vol->mesh(); + Slic3r::sla::IndexedMesh indexed_mesh(mesh); // more user-friendly + out_cpp << "TriangleMesh vol_"<< idx_obj << "_" << idx_vol <<" = TriangleMesh(std::vector{"; + int ptidx= 0; + for(const Slic3r::Vec3f &pt : indexed_mesh.vertices()) + out_cpp << (0==ptidx++?"{":",{") << Slic3r::to_string_nozero(pt.x(), 7) + << ',' << Slic3r::to_string_nozero(pt.y(), 7) + << ',' << Slic3r::to_string_nozero(pt.z(), 7) << '}'; + out_cpp << "},std::vector{"; + ptidx= 0; + for(const Slic3r::Vec3i32 &tri : indexed_mesh.indices()) + out_cpp << (0==ptidx++?"{":",{") << tri(0) << ',' << tri(1) << ',' << tri(2) << '}'; + out_cpp << "});\n"; + + idx_vol++; + } + out_cpp << "\n"; + idx_obj++; + } + + clipboard << out_cpp.str(); + std::cout << out_cpp.str(); + + return 0; +} diff --git a/tests/superslicerlibslic3r/CMakeLists.txt b/tests/superslicerlibslic3r/CMakeLists.txt index 150400ef9fd..63d0f96d2f1 100644 --- a/tests/superslicerlibslic3r/CMakeLists.txt +++ b/tests/superslicerlibslic3r/CMakeLists.txt @@ -1,31 +1,30 @@ get_filename_component(_TEST_NAME ${CMAKE_CURRENT_LIST_DIR} NAME) -add_executable(${_TEST_NAME}_tests - ${_TEST_NAME}_tests.cpp - test_complete_objects.cpp - # test_fill.cpp - # test_flow.cpp - # test_gcodewriter.cpp - # test_geometry.cpp - # test_model.cpp - test_print.cpp - # test_thin.cpp - # test_denserinfill.cpp - # test_extrusion_entity.cpp - # test_skirt_brim.cpp - test_data.hpp - test_data.cpp - # test_clipper_utils.cpp - test_dense_infill.cpp - ) - -target_link_libraries(${_TEST_NAME}_tests test_common libslic3r) -set_property(TARGET ${_TEST_NAME}_tests PROPERTY FOLDER "tests") +function(create_test test_name) + add_executable(${test_name}_test + ${test_name}.cpp + test_data.hpp + test_data.cpp + ) + target_link_libraries(${test_name}_test test_common libslic3r) + set_property(TARGET ${test_name}_test PROPERTY FOLDER "tests") + if (WIN32) + prusaslicer_copy_dlls(${test_name}_test) + endif() + add_test(${test_name}_test ${test_name}_test ${CATCH_EXTRA_ARGS}) +endfunction() -if (WIN32) - prusaslicer_copy_dlls(${_TEST_NAME}_tests) -endif() - -# catch_discover_tests(${_TEST_NAME}_tests TEST_PREFIX "${_TEST_NAME}: ") -add_test(${_TEST_NAME}_tests ${_TEST_NAME}_tests ${CATCH_EXTRA_ARGS}) +create_test(test_complete_objects) +create_test(test_clipper_utils) +create_test(test_dense_infill) +create_test(test_denserinfill) +create_test(test_extrusion_entity) +create_test(test_fill) +create_test(test_flow) +create_test(test_gcodewriter) +create_test(test_geometry) +create_test(test_model) +create_test(test_print) +create_test(test_skirt_brim) +create_test(test_thin) diff --git a/tests/superslicerlibslic3r/test_clipper_utils.cpp b/tests/superslicerlibslic3r/test_clipper_utils.cpp index e30379e4e4e..0af733e2d3f 100644 --- a/tests/superslicerlibslic3r/test_clipper_utils.cpp +++ b/tests/superslicerlibslic3r/test_clipper_utils.cpp @@ -1,4 +1,5 @@ -#include + +#include #include #include @@ -34,7 +35,7 @@ SCENARIO("Various Clipper operations - xs/t/11_clipper.t", "[ClipperUtils]") { } } WHEN("offset2_ex") { - ExPolygons result = Slic3r::offset2_ex(square_with_hole, 5.f, -2.f); + ExPolygons result = Slic3r::offset2_ex({square_with_hole}, 5.f, -2.f); THEN("offset matches") { REQUIRE(result == ExPolygons { { { { 203, 203 }, { 97, 203 }, { 97, 97 }, { 203, 97 } }, @@ -56,7 +57,7 @@ SCENARIO("Various Clipper operations - xs/t/11_clipper.t", "[ClipperUtils]") { } GIVEN("square and hole") { WHEN("diff_ex") { - ExPolygons result = Slic3r::diff_ex({ square }, { hole_in_square }); + ExPolygons result = Slic3r::diff_ex(Polygons{ square }, Polygons{ hole_in_square }); THEN("hole is created") { REQUIRE(result.size() == 1); REQUIRE(square_with_hole.area() == result.front().area()); @@ -64,7 +65,7 @@ SCENARIO("Various Clipper operations - xs/t/11_clipper.t", "[ClipperUtils]") { } } GIVEN("polyline") { - Polyline polyline { { 50, 150 }, { 300, 150 } }; + Slic3r::Polyline polyline { { 50, 150 }, { 300, 150 } }; WHEN("intersection_pl") { Polylines result = Slic3r::intersection_pl({ polyline }, { square, hole_in_square }); THEN("correct number of result lines") { @@ -77,19 +78,19 @@ SCENARIO("Various Clipper operations - xs/t/11_clipper.t", "[ClipperUtils]") { } } WHEN("diff_pl") { - Polylines result = Slic3r::diff_pl({ polyline }, { square, hole_in_square }); + Polylines result = Slic3r::diff_pl(Polylines{ polyline }, Polygons{ square, hole_in_square }); THEN("correct number of result lines") { REQUIRE(result.size() == 3); } // results are in no particular order THEN("the left result line has correct length") { - REQUIRE(std::count_if(result.begin(), result.end(), [](const Polyline &pl) { return pl.length() == 50; }) == 1); + REQUIRE(std::count_if(result.begin(), result.end(), [](const Slic3r::Polyline &pl) { return pl.length() == 50; }) == 1); } THEN("the right result line has correct length") { - REQUIRE(std::count_if(result.begin(), result.end(), [](const Polyline &pl) { return pl.length() == 100; }) == 1); + REQUIRE(std::count_if(result.begin(), result.end(), [](const Slic3r::Polyline &pl) { return pl.length() == 100; }) == 1); } THEN("the central result line has correct length") { - REQUIRE(std::count_if(result.begin(), result.end(), [](const Polyline &pl) { return pl.length() == 20; }) == 1); + REQUIRE(std::count_if(result.begin(), result.end(), [](const Slic3r::Polyline &pl) { return pl.length() == 20; }) == 1); } } } @@ -99,8 +100,11 @@ SCENARIO("Various Clipper operations - xs/t/11_clipper.t", "[ClipperUtils]") { { 74730000, 74730000 }, { 55270000, 74730000 }, { 55270000, 68063296 }, { 44730000, 68063296 }, { 44730000, 74730000 }, { 25270000, 74730000 }, { 25270000, 55270000 }, { 31936670, 55270000 }, { 31936670, 44730000 }, { 25270000, 44730000 }, { 25270000, 25270000 }, { 44730000, 25270000 }, { 44730000, 31936670 } }; Slic3r::Polygon clip { {75200000, 45200000}, {54800000, 45200000}, {54800000, 24800000}, {75200000, 24800000} }; - Slic3r::Polylines result = Slic3r::intersection_pl({ subject }, { clip }); + Slic3r::Polylines result = Slic3r::intersection_pl(Polylines{ subject }, clip); THEN("intersection_pl - result is not empty") { + REQUIRE(result.size() == 1); } + result = Slic3r::intersection_pl(subject, Polygons{clip}); + THEN("intersection_pl(2) - result is not empty") { REQUIRE(result.size() == 1); } } @@ -108,22 +112,41 @@ SCENARIO("Various Clipper operations - xs/t/11_clipper.t", "[ClipperUtils]") { Slic3r::Polyline subject { { 1975, 1975 }, { 25, 1975 }, { 25, 25 }, { 1975, 25 }, { 1975, 1975 } }; Slic3r::Polygons clip { { { 2025, 2025 }, { -25, 2025 } , { -25, -25 }, { 2025, -25 } }, { { 525, 525 }, { 525, 1475 }, { 1475, 1475 }, { 1475, 525 } } }; - Slic3r::Polylines result = Slic3r::intersection_pl({ subject }, clip); + Slic3r::Polylines result = Slic3r::intersection_pl(Polylines{ subject }, clip); THEN("intersection_pl - result is not empty") { REQUIRE(result.size() == 1); REQUIRE(result.front().points.size() == 5); } + result = Slic3r::intersection_pl(subject, Polygons{clip}); + THEN("intersection_pl(2) - result is not empty") { + REQUIRE(result.size() == 1); + REQUIRE(result.front().points.size() == 5); + } } GIVEN("Clipper bug #126") { Slic3r::Polyline subject { { 200000, 19799999 }, { 200000, 200000 }, { 24304692, 200000 }, { 15102879, 17506106 }, { 13883200, 19799999 }, { 200000, 19799999 } }; Slic3r::Polygon clip { { 15257205, 18493894 }, { 14350057, 20200000 }, { -200000, 20200000 }, { -200000, -200000 }, { 25196917, -200000 } }; - Slic3r::Polylines result = Slic3r::intersection_pl({ subject }, { clip }); + Slic3r::Polylines result = Slic3r::intersection_pl(Polylines{ subject }, clip); THEN("intersection_pl - result is not empty") { REQUIRE(result.size() == 1); } THEN("intersection_pl - result has same length as subject polyline") { REQUIRE(result.front().length() == Approx(subject.length())); } + result = Slic3r::intersection_pl(subject, Polygons{clip}); + THEN("intersection_pl(2) - result is not empty") { + REQUIRE(result.size() == 1); + } + THEN("intersection_pl(2) - result has same length as subject polyline") { + REQUIRE(result.front().length() == Approx(subject.length())); + } + result = Slic3r::intersection_pl(Polylines{subject}, Polygons{clip}); + THEN("intersection_pl(3) - result is not empty") { + REQUIRE(result.size() == 1); + } + THEN("intersection_pl(3) - result has same length as subject polyline") { + REQUIRE(result.front().length() == Approx(subject.length())); + } } #if 0 @@ -180,7 +203,7 @@ SCENARIO("Various Clipper operations - t/clipper.t", "[ClipperUtils]") { // CW oriented contour Slic3r::Polygon hole_in_square { { 14, 14 }, { 14, 16 }, { 16, 16 }, { 16, 14 } }; WHEN("intersection_ex with another square") { - ExPolygons intersection = Slic3r::intersection_ex({ square, hole_in_square }, { square2 }); + ExPolygons intersection = Slic3r::intersection_ex(Polygons{ square, hole_in_square }, Polygons{ square2 }); THEN("intersection area matches (hole is preserved)") { ExPolygon match({ { 20, 18 }, { 10, 18 }, { 10, 12 }, { 20, 12 } }, { { 14, 16 }, { 16, 16 }, { 16, 14 }, { 14, 14 } }); @@ -196,14 +219,14 @@ SCENARIO("Various Clipper operations - t/clipper.t", "[ClipperUtils]") { // CW oriented contour Slic3r::Polygon hole { { 15, 15 }, { 15, 25 }, { 25, 25 }, {25, 15 } }; WHEN("union_ex with another square") { - ExPolygons union_ = Slic3r::union_ex({ square, square2, hole }); + ExPolygons union_ = Slic3r::union_ex(Polygons{ square, square2, hole }); THEN("union of two ccw and one cw is a contour with no holes") { REQUIRE(union_.size() == 1); REQUIRE(union_.front() == ExPolygon { { 40, 40 }, { 0, 40 }, { 0, 0 }, { 40, 0 } } ); } } WHEN("diff_ex with another square") { - ExPolygons diff = Slic3r::diff_ex({ square, square2 }, { hole }); + ExPolygons diff = Slic3r::diff_ex(Polygons{ square, square2 }, Polygons{ hole }); THEN("difference of a cw from two ccw is a contour with one hole") { REQUIRE(diff.size() == 1); REQUIRE(diff.front().area() == Approx(ExPolygon({ {40, 40}, {0, 40}, {0, 0}, {40, 0} }, { {15, 25}, {25, 25}, {25, 15}, {15, 15} }).area())); @@ -244,26 +267,26 @@ size_t count_polys(const ExPolygons& expolys) TEST_CASE("Traversing Clipper PolyTree", "[ClipperUtils]") { // Create a polygon representing unit box - Polygon unitbox; + Slic3r::Polygon unitbox; const int32_t UNIT = int32_t(1. / SCALING_FACTOR); unitbox.points = Points{Point{0, 0}, Point{UNIT, 0}, Point{UNIT, UNIT}, Point{0, UNIT}}; - Polygon box_frame = unitbox; + Slic3r::Polygon box_frame = unitbox; box_frame.scale(20, 10); - Polygon hole_left = unitbox; + Slic3r::Polygon hole_left = unitbox; hole_left.scale(8); hole_left.translate(UNIT, UNIT); hole_left.reverse(); - Polygon hole_right = hole_left; + Slic3r::Polygon hole_right = hole_left; hole_right.translate(UNIT * 10, 0); - Polygon inner_left = unitbox; + Slic3r::Polygon inner_left = unitbox; inner_left.scale(4); inner_left.translate(UNIT * 3, UNIT * 3); - Polygon inner_right = inner_left; + Slic3r::Polygon inner_right = inner_left; inner_right.translate(UNIT * 10, 0); Polygons reference = union_({box_frame, hole_left, hole_right, inner_left, inner_right}); @@ -299,3 +322,90 @@ TEST_CASE("Traversing Clipper PolyTree", "[ClipperUtils]") { REQUIRE(count_polys(output) == reference.size()); } } + +TEST_CASE("Testing ", "[ClipperUtils]") { + Slic3r::Polygon src_polygon( + {{-29766902, -30710288}, {-30290102, -30802646}, {-30799114, -30715083}, {-31876243, -30562718}, + {-33030941, -30449754}, {-33231822, -30436946}, {-34268178, -30384775}, {-34891023, -30367930}, + {-34938429, -30367343}, {-36307009, -30380364}, {-36686920, -30395327}, {-38057500, -30465424}, + {-38066183, -30465841}, {-39121269, -30543247}, {-39144586, -30545052}, {-41393647, -30762768}, + {-41400772, -30763367}, {-42606470, -30898534}, {-43049745, -30951762}, {-43526989, -31152101}, + {-44543970, -31296610}, {-49896253, -32067648}, {-53031149, -32453333}, {-54983432, -32629283}, + {-55876108, -32681239}, {-57207787, -32710144}, {-57287031, -32707371}, {-56999037, -31773098}, + {-57020109, -31574537}, {-57153102, -31460716}, {-59114378, -30732754}, {-59554951, -30452156}, + {-59664101, -30265002}, {-59753496, -29913462}, {-59728476, -29015470}, {-59648533, -27590938}, + {-59696516, -27427759}, {-59871882, -27324947}, {-60861946, -27207800}, {-60553293, -26514064}, + {-60221446, -25827699}, {-59983819, -25377161}, {-59431848, -24334493}, {-58071530, -22002475}, + {-57086298, -20406564}, {-54532068, -16383584}, {-54152045, -16033352}, {-53418323, -14810628}, + {-53037302, -14152026}, {-52585902, -13384179}, {-52093130, -12530959}, {-52089199, -12523696}, + {-51416049, -11301170}, {-51399188, -11269626}, {-50899221, -10293557}, {-50548785, -9599755}, + {-50422361, -9325954}, {-49913114, -8198227}, {-49857361, -8070473}, {-49486084, -7130146}, + {-49262185, -6546354}, {-48814997, -5175926}, {-48666648, -4650820}, {-48416355, -3640670}, + {-48173788, -2389333}, {-48059689, -1542776}, {-47989236, -963142}, {-47988421, -954092}, + {-47908090, 106824}, {-47878053, 573422}, {-47849952, 1687025}, {-47645107, 4755332}, + {-47768143, 5288883}, {-47768047, 5291706}, {-47527604, 7621018}, {-47663943, 7838131}, + {-47525823, 8455742}, {-47689343, 9155509}, {-47795210, 10268834}, {-47978714, 11428999}, + {-48194112, 12344043}, {-48481144, 13309478}, {-48642179, 13794190}, {-48842780, 14334161}, + {-49197836, 15187901}, {-49588991, 16033320}, {-49853153, 16562549}, {-50513053, 17792804}, + {-50882667, 18419696}, {-51438514, 19339116}, {-51718684, 19773192}, {-52179489, 20475205}, + {-52491489, 20942905}, {-52496021, 20949622}, {-53290936, 22086329}, {-53752870, 22724706}, + {-54177967, 23303509}, {-54181286, 23308060}, {-55141698, 24578760}, {-55144467, 24582493}, + {-55936527, 25607586}, {-56390354, 26180675}, {-56401601, 26194795}, {-57375148, 27425084}, + {-57796140, 27725621}, {-58510273, 28592781}, {-65026204, 36326237}, {-66321141, 37899688}, + {-67553055, 39431322}, {-68707652, 40912081}, {-69414421, 41847539}, {-70373648, 43171709}, + {-70802160, 43801970}, {-69626708, 44423826}, {-69500832, 44580612}, {-69517438, 44759180}, + {-70402232, 46571248}, {-70631353, 47139129}, {-70790322, 47645204}, {-70880079, 48170004}, + {-70836022, 48432201}, {-70393757, 48597581}, {-69696951, 48717065}, {-69166672, 48746854}, + {-66168401, 48719007}, {-66004571, 48777066}, {-65913199, 48953792}, {-65819709, 50214929}, + {-64567977, 49966674}, {-63318168, 49705469}, {-60009943, 48909169}, {-56515788, 47981280}, + {-54126539, 47316536}, {-46386391, 45110400}, {-43369296, 44277479}, {-40263700, 43467720}, + {-39395835, 43264181}, {-37625205, 42849082}, {-37483166, 42819432}, {-36253801, 42563516}, + {-35674412, 42454458}, {-35515136, 42424491}, {-35048870, 42199191}, {-34862709, 42168781}, + {-33252621, 41926411}, {-32502942, 41835599}, {-31999592, 41778303}, {-31076021, 41691629}, + {-30193707, 41636746}, {-29260187, 41590640}, {-29176144, 41589180}, {-28142088, 41581326}, + {-27548623, 41596261}, {-26950500, 41621514}, {-26907420, 41624187}, {-27296983, 41112633}, + {-27381326, 40996047}, {-27989012, 40963451}, {-28138692, 40959253}, {-29172601, 40940110}, + {-30216723, 40958086}, {-30968347, 40990968}, {-32059596, 41069576}, {-32574047, 41111839}, + {-33323922, 41188523}, {-33355502, 41192102}, {-34970203, 41401547}, {-35176124, 41432378}, + {-35690171, 41369764}, {-36438808, 41490323}, {-37698617, 41699347}, {-39653744, 42065692}, + {-43800396, 42915182}, {-45342457, 43261526}, {-45348345, 43262775}, {-50568599, 44305692}, + {-50574460, 44306791}, {-53615613, 44840310}, {-53623507, 44841566}, {-55534335, 45114997}, + {-56455716, 45222015}, {-56990415, 45265339}, {-58176151, 45361070}, {-58988986, 45390201}, + {-59754351, 45388396}, {-60364211, 45358767}, {-61360217, 45251837}, {-62159687, 45076387}, + {-62794134, 44850846}, {-63424043, 44497175}, {-63912607, 44054027}, {-64275381, 43487793}, + {-64498459, 42717071}, {-64535148, 42192268}, {-64471205, 41405650}, {-64314543, 40690545}, + {-64120100, 40058090}, {-63874462, 39404122}, {-63581000, 38726318}, {-63242248, 38023061}, + {-63048962, 37665614}, {-62451850, 36563209}, {-61998277, 35793781}, {-61994661, 35787838}, + {-61010738, 34219433}, {-61006329, 34212647}, {-59353428, 31755703}, {-58915997, 31155400}, + {-58904968, 31139811}, {-58173450, 30074020}, {-57605465, 29308774}, {-57267309, 28853350}, + {-56935597, 28379741}, {-56758677, 27893678}, {-55833774, 26626414}, {-55384145, 26031982}, + {-55378724, 26024436}, {-54620031, 24974408}, {-54614601, 24966864}, {-53686336, 23672495}, + {-53263954, 23077836}, {-52819950, 22424397}, {-52812898, 22413958}, {-52039562, 21262463}, + {-51720551, 20779964}, {-51268827, 20062375}, {-51004463, 19621601}, {-50993923, 19603829}, + {-50450501, 18677012}, {-50134549, 18108099}, {-49637035, 17140780}, {-49202252, 16226805}, + {-48915776, 15586329}, {-48502177, 14536860}, {-48293881, 13926867}, {-48131171, 13424218}, + {-47957911, 12802996}, {-47710562, 11741154}, {-47547264, 10744476}, {-47411827, 9350391}, + {-47399989, 9163312}, {-47526019, 8468044}, {-47381692, 7839505}, {-47527604, 7621018}, + {-47487457, 5279674}, {-47644915, 4762661}, {-47645107, 4755332}, {-47560209, 1681367}, + {-47560253, 1679345}, {-47591199, 565817}, {-47610875, 84616}, {-47689099, -976457}, + {-47742308, -1576171}, {-47842045, -2389891}, {-47996471, -3333559}, {-48219314, -4396851}, + {-48438557, -5270192}, {-48712153, -6237043}, {-49060161, -7284025}, {-49063021, -7292452}, + {-49415948, -8239818}, {-49473812, -8389762}, {-49953551, -9530354}, {-50412680, -10529202}, + {-50415227, -10534771}, {-50893546, -11521628}, {-50916067, -11567425}, {-51554754, -12808303}, + {-52019235, -13695926}, {-52446210, -14467999}, {-52801876, -15142704}, {-52808818, -15155800}, + {-53480037, -16413921}, {-53584936, -16919960}, {-53843700, -17435906}, {-53846126, -17440877}, + {-54868733, -19595920}, {-54872166, -19603470}, {-55326937, -20648845}, {-55543581, -21190124}, + {-55680915, -21533885}, {-56036127, -22524045}, {-56325917, -23486648}, {-56536000, -24407114}, + {-56625601, -25224967}, {-56678029, -25738177}, {-56653328, -26373647}, {-56547823, -26988562}, + {-56342934, -27593803}, {-56040970, -28128453}, {-55803719, -28427693}, {-55381973, -28822864}, + {-54839359, -29182948}, {-54386222, -29398844}, {-53567537, -29700868}, {-52853584, -29879786}, + {-52093673, -30015999}, {-51292005, -30115523}, {-50452932, -30183406}, {-49578991, -30224183}, + {-49569346, -30224448}, {-47759328, -30239656}, {-47749986, -30239561}, {-45372177, -30171922}, + {-44666915, -30125409}, {-43916922, -30103842}, {-43639264, -30083267}, {-43130808, -30180062}, + {-42674180, -30139307}, {-41463591, -30058983}, {-41449327, -30058073}, {-39193983, -29919875}, + {-39155994, -29917901}, {-38098825, -29878010}, {-38081454, -29877418}, {-36709714, -29835798}, + {-36306241, -29836742}, {-34937704, -29853628}, {-34254369, -29892783}, {-34238932, -29893784}, + {-33203711, -29965009}, {-32164627, -30082538}, {-31146078, -30236999}, {-30227180, -30411554}, + {-29766902, -30710288}}); + +} diff --git a/tests/superslicerlibslic3r/test_complete_objects.cpp b/tests/superslicerlibslic3r/test_complete_objects.cpp index 5ff5bd7d45c..85d7d364355 100644 --- a/tests/superslicerlibslic3r/test_complete_objects.cpp +++ b/tests/superslicerlibslic3r/test_complete_objects.cpp @@ -1,7 +1,6 @@ -#define CATCH_CONFIG_DISABLE -#include -//#include +//#define CATCH_CONFIG_DISABLE +#include #include #include "test_data.hpp" @@ -38,7 +37,7 @@ std::unique_ptr init_print_with_dist(DynamicPrintConfig &config, float di if (distance <= 0) { print->apply(model, config); - arrange_objects(model, InfiniteBed{}, ArrangeParams{ scaled(/*min_object_distance(config)) });/*/ PrintConfig::min_object_distance(&print->config(), 999999)) }); + arrange_objects(model, InfiniteBed{}, ArrangeParams{ scale_t(10)/*min_object_distance(config)) }); PrintConfig::min_object_distance(&print->config(), 999999))/*/ }); model.center_instances_around_point(Slic3r::Vec2d(100, 100)); } @@ -51,15 +50,16 @@ std::unique_ptr init_print_with_dist(DynamicPrintConfig &config, float di SCENARIO("Complete objects separatly") { GIVEN("20mm cubes and extruder_clearance_radius to 10") { + ConfigSubstitutionContext subst(ForwardCompatibilitySubstitutionRule::Disable); DynamicPrintConfig& config = Slic3r::DynamicPrintConfig::full_print_config(); config.set_key_value("fill_density", new ConfigOptionPercent(0)); - config.set_deserialize("nozzle_diameter", "0.4"); - config.set_deserialize("layer_height", "0.3"); - config.set_deserialize("extruder_clearance_height", "50"); - config.set_deserialize("extruder_clearance_radius", "10"); - config.set_deserialize("skirts", "0"); - config.set_deserialize("skirt_height", "0"); - config.set_deserialize("brim_width", "0"); + config.set_deserialize("nozzle_diameter", "0.4", subst); + config.set_deserialize("layer_height", "0.3", subst); + config.set_deserialize("extruder_clearance_height", "50", subst); + config.set_deserialize("extruder_clearance_radius", "10", subst); + config.set_deserialize("skirts", "0", subst); + config.set_deserialize("skirt_height", "0", subst); + config.set_deserialize("brim_width", "0", subst); std::pair result; @@ -93,7 +93,7 @@ SCENARIO("Complete objects separatly") { } WHEN("with a 10 mm brim, so the dist should be 40mm ") { config.set_key_value("complete_objects", new ConfigOptionBool(true)); - config.set_deserialize("brim_width", "10"); + config.set_deserialize("brim_width", "10", subst); THEN("(too near)") { result = init_print_with_dist(config, 39.9)->validate(); REQUIRE(result.first == PrintBase::PrintValidationError::pveWrongPosition); @@ -106,10 +106,10 @@ SCENARIO("Complete objects separatly") { } WHEN("with a 10 mm dist short skirt, so the dist should be 40mm +extrusionwidth") { config.set_key_value("complete_objects", new ConfigOptionBool(true)); - config.set_deserialize("skirts", "1"); - config.set_deserialize("skirt_height", "1"); - config.set_deserialize("skirt_distance", "10"); - config.set_deserialize("complete_objects_one_skirt", "0"); + config.set_deserialize("skirts", "1", subst); + config.set_deserialize("skirt_height", "1", subst); + config.set_deserialize("skirt_distance", "10", subst); + config.set_deserialize("complete_objects_one_skirt", "0", subst); THEN("(too near)") { result = init_print_with_dist(config, 40)->validate(); @@ -125,15 +125,16 @@ SCENARIO("Complete objects separatly") { } SCENARIO("Arrange is good enough") { GIVEN("20mm cubes and extruder_clearance_radius to 10") { + ConfigSubstitutionContext subst(ForwardCompatibilitySubstitutionRule::Disable); DynamicPrintConfig& config = Slic3r::DynamicPrintConfig::full_print_config(); config.set_key_value("fill_density", new ConfigOptionPercent(0)); - config.set_deserialize("nozzle_diameter", "0.4"); - config.set_deserialize("layer_height", "0.3"); - config.set_deserialize("extruder_clearance_height", "50"); - config.set_deserialize("extruder_clearance_radius", "10"); - config.set_deserialize("skirts", "0"); - config.set_deserialize("skirt_height", "0"); - config.set_deserialize("brim_width", "0"); + config.set_deserialize("nozzle_diameter", "0.4", subst); + config.set_deserialize("layer_height", "0.3", subst); + config.set_deserialize("extruder_clearance_height", "50", subst); + config.set_deserialize("extruder_clearance_radius", "10", subst); + config.set_deserialize("skirts", "0", subst); + config.set_deserialize("skirt_height", "0", subst); + config.set_deserialize("brim_width", "0", subst); std::pair result; @@ -148,16 +149,16 @@ SCENARIO("Arrange is good enough") { } WHEN("complete objects whith brim") { config.set_key_value("complete_objects", new ConfigOptionBool(true)); - config.set_deserialize("brim_width", "10"); + config.set_deserialize("brim_width", "10", subst); result = init_print_with_dist(config, -1)->validate(); REQUIRE(result.second == ""); } WHEN("complete objects whith skirt") { config.set_key_value("complete_objects", new ConfigOptionBool(true)); - config.set_deserialize("skirts", "1"); - config.set_deserialize("skirt_height", "1"); - config.set_deserialize("skirt_distance", "10"); - config.set_deserialize("complete_objects_one_skirt", "0"); + config.set_deserialize("skirts", "1", subst); + config.set_deserialize("skirt_height", "1", subst); + config.set_deserialize("skirt_distance", "10", subst); + config.set_deserialize("complete_objects_one_skirt", "0", subst); result = init_print_with_dist(config, -1)->validate(); REQUIRE(result.second == ""); } diff --git a/tests/superslicerlibslic3r/test_data.cpp b/tests/superslicerlibslic3r/test_data.cpp index 23a19ffce5a..659249b77cc 100644 --- a/tests/superslicerlibslic3r/test_data.cpp +++ b/tests/superslicerlibslic3r/test_data.cpp @@ -48,106 +48,106 @@ const std::unordered_map mesh_names { TriangleMesh mesh(TestMesh m) { std::vector facets; - std::vector vertices; + std::vector vertices; switch(m) { case TestMesh::cube_with_hole: - vertices = { Vec3d(0,0,0), Vec3d(0,0,10), Vec3d(0,20,0), Vec3d(0,20,10), Vec3d(20,0,0), Vec3d(20,0,10), Vec3d(5,5,0), Vec3d(15,5,0), Vec3d(5,15,0), Vec3d(20,20,0), Vec3d(15,15,0), Vec3d(20,20,10), Vec3d(5,5,10), Vec3d(5,15,10), Vec3d(15,5,10), Vec3d(15,15,10) }; + vertices = { Vec3f(0,0,0), Vec3f(0,0,10), Vec3f(0,20,0), Vec3f(0,20,10), Vec3f(20,0,0), Vec3f(20,0,10), Vec3f(5,5,0), Vec3f(15,5,0), Vec3f(5,15,0), Vec3f(20,20,0), Vec3f(15,15,0), Vec3f(20,20,10), Vec3f(5,5,10), Vec3f(5,15,10), Vec3f(15,5,10), Vec3f(15,15,10) }; facets = std::vector{ Vec3i32(0,1,2), Vec3i32(2,1,3), Vec3i32(1,0,4), Vec3i32(5,1,4), Vec3i32(6,7,4), Vec3i32(8,2,9), Vec3i32(0,2,8), Vec3i32(10,8,9), Vec3i32(0,8,6), Vec3i32(0,6,4), Vec3i32(4,7,9), Vec3i32(7,10,9), Vec3i32(2,3,9), Vec3i32(9,3,11), Vec3i32(12,1,5), Vec3i32(13,3,12), Vec3i32(14,12,5), Vec3i32(3,1,12), Vec3i32(11,3,13), Vec3i32(11,15,5), Vec3i32(11,13,15), Vec3i32(15,14,5), Vec3i32(5,4,9), Vec3i32(11,5,9), Vec3i32(8,13,12), Vec3i32(6,8,12), Vec3i32(10,15,13), Vec3i32(8,10,13), Vec3i32(15,10,14), Vec3i32(14,10,7), Vec3i32(14,7,12), Vec3i32(12,7,6) }; break; case TestMesh::cube_with_concave_hole: - vertices = std::vector{ - Vec3d(-10,-10,-5), Vec3d(-10,-10,5), Vec3d(-10,10,-5), Vec3d(-10,10,5), Vec3d(10,-10,-5), Vec3d(10,-10,5), Vec3d(-5,-5,-5), Vec3d(5,-5,-5), Vec3d(5,5,-5), Vec3d(5,10,-5), Vec3d(-5,5,-5), Vec3d(3.06161699911402e-16,5,-5), Vec3d(5,0,-5), Vec3d(0,0,-5), Vec3d(10,5,-5), Vec3d(5,10,5), Vec3d(-5,-5,5), Vec3d(5,0,5), Vec3d(5,-5,5), Vec3d(-5,5,5), Vec3d(10,5,5), Vec3d(5,5,5), Vec3d(3.06161699911402e-16,5,5), Vec3d(0,0,5) + vertices = std::vector{ + Vec3f(-10,-10,-5), Vec3f(-10,-10,5), Vec3f(-10,10,-5), Vec3f(-10,10,5), Vec3f(10,-10,-5), Vec3f(10,-10,5), Vec3f(-5,-5,-5), Vec3f(5,-5,-5), Vec3f(5,5,-5), Vec3f(5,10,-5), Vec3f(-5,5,-5), Vec3f(0,5,-5), Vec3f(5,0,-5), Vec3f(0,0,-5), Vec3f(10,5,-5), Vec3f(5,10,5), Vec3f(-5,-5,5), Vec3f(5,0,5), Vec3f(5,-5,5), Vec3f(-5,5,5), Vec3f(10,5,5), Vec3f(5,5,5), Vec3f(0,5,5), Vec3f(0,0,5) }; facets = std::vector{ Vec3i32(0,1,2), Vec3i32(2,1,3), Vec3i32(1,0,4), Vec3i32(5,1,4), Vec3i32(6,7,4), Vec3i32(8,2,9), Vec3i32(10,2,11), Vec3i32(11,12,13), Vec3i32(0,2,10), Vec3i32(0,10,6), Vec3i32(0,6,4), Vec3i32(11,2,8), Vec3i32(4,7,12), Vec3i32(4,12,8), Vec3i32(12,11,8), Vec3i32(14,4,8), Vec3i32(2,3,9), Vec3i32(9,3,15), Vec3i32(16,1,5), Vec3i32(17,18,5), Vec3i32(19,3,16), Vec3i32(20,21,5), Vec3i32(18,16,5), Vec3i32(3,1,16), Vec3i32(22,3,19), Vec3i32(21,3,22), Vec3i32(21,17,5), Vec3i32(21,22,17), Vec3i32(21,15,3), Vec3i32(23,17,22), Vec3i32(5,4,14), Vec3i32(20,5,14), Vec3i32(20,14,21), Vec3i32(21,14,8), Vec3i32(9,15,21), Vec3i32(8,9,21), Vec3i32(10,19,16), Vec3i32(6,10,16), Vec3i32(11,22,19), Vec3i32(10,11,19), Vec3i32(13,23,11), Vec3i32(11,23,22), Vec3i32(23,13,12), Vec3i32(17,23,12), Vec3i32(17,12,18), Vec3i32(18,12,7), Vec3i32(18,7,16), Vec3i32(16,7,6) }; break; case TestMesh::V: - vertices = std::vector{ - Vec3d(-14,0,20), Vec3d(-14,15,20), Vec3d(0,0,0), Vec3d(0,15,0), Vec3d(-4,0,20), Vec3d(-4,15,20), Vec3d(5,0,7.14286), Vec3d(10,0,0), Vec3d(24,0,20), Vec3d(14,0,20), Vec3d(10,15,0), Vec3d(5,15,7.14286), Vec3d(14,15,20), Vec3d(24,15,20) + vertices = std::vector{ + Vec3f(-14,0,20), Vec3f(-14,15,20), Vec3f(0,0,0), Vec3f(0,15,0), Vec3f(-4,0,20), Vec3f(-4,15,20), Vec3f(5,0,7.14286), Vec3f(10,0,0), Vec3f(24,0,20), Vec3f(14,0,20), Vec3f(10,15,0), Vec3f(5,15,7.14286f), Vec3f(14,15,20), Vec3f(24,15,20) }; facets = std::vector{ Vec3i32(0,1,2), Vec3i32(2,1,3), Vec3i32(1,0,4), Vec3i32(5,1,4), Vec3i32(4,0,2), Vec3i32(6,4,2), Vec3i32(7,6,2), Vec3i32(8,9,7), Vec3i32(9,6,7), Vec3i32(2,3,7), Vec3i32(7,3,10), Vec3i32(1,5,3), Vec3i32(3,5,11), Vec3i32(11,12,13), Vec3i32(11,13,3), Vec3i32(3,13,10), Vec3i32(5,4,6), Vec3i32(11,5,6), Vec3i32(6,9,11), Vec3i32(11,9,12), Vec3i32(12,9,8), Vec3i32(13,12,8), Vec3i32(8,7,10), Vec3i32(13,8,10) }; break; case TestMesh::L: - vertices = std::vector{ - Vec3d(0,10,0), Vec3d(0,10,10), Vec3d(0,20,0), Vec3d(0,20,10), Vec3d(10,10,0), Vec3d(10,10,10), Vec3d(20,20,0), Vec3d(20,0,0), Vec3d(10,0,0), Vec3d(20,20,10), Vec3d(10,0,10), Vec3d(20,0,10) + vertices = std::vector{ + Vec3f(0,10,0), Vec3f(0,10,10), Vec3f(0,20,0), Vec3f(0,20,10), Vec3f(10,10,0), Vec3f(10,10,10), Vec3f(20,20,0), Vec3f(20,0,0), Vec3f(10,0,0), Vec3f(20,20,10), Vec3f(10,0,10), Vec3f(20,0,10) }; facets = std::vector{ Vec3i32(0,1,2), Vec3i32(2,1,3), Vec3i32(4,5,1), Vec3i32(0,4,1), Vec3i32(0,2,4), Vec3i32(4,2,6), Vec3i32(4,6,7), Vec3i32(4,7,8), Vec3i32(2,3,6), Vec3i32(6,3,9), Vec3i32(3,1,5), Vec3i32(9,3,5), Vec3i32(10,11,5), Vec3i32(11,9,5), Vec3i32(5,4,10), Vec3i32(10,4,8), Vec3i32(10,8,7), Vec3i32(11,10,7), Vec3i32(11,7,6), Vec3i32(9,11,6) }; break; case TestMesh::overhang: - vertices = std::vector{ - Vec3d(1364.68505859375,614.398010253906,20.002498626709), Vec3d(1389.68505859375,614.398010253906,20.002498626709), Vec3d(1377.18505859375,589.398986816406,20.002498626709), Vec3d(1389.68505859375,589.398986816406,20.002498626709), Vec3d(1389.68505859375,564.398986816406,20.0014991760254), Vec3d(1364.68505859375,589.398986816406,20.002498626709), Vec3d(1364.68505859375,564.398986816406,20.0014991760254), Vec3d(1360.93505859375,589.398986816406,17.0014991760254), Vec3d(1360.93505859375,585.64697265625,17.0014991760254), Vec3d(1357.18505859375,564.398986816406,17.0014991760254), Vec3d(1364.68505859375,589.398986816406,17.0014991760254), Vec3d(1364.68505859375,571.899963378906,17.0014991760254), Vec3d(1364.68505859375,564.398986816406,17.0014991760254), Vec3d(1348.43603515625,564.398986816406,17.0014991760254), Vec3d(1352.80908203125,589.398986816406,17.0014991760254), Vec3d(1357.18408203125,589.398986816406,17.0014991760254), Vec3d(1357.18310546875,614.398010253906,17.0014991760254), Vec3d(1364.68505859375,606.89599609375,17.0014991760254), Vec3d(1364.68505859375,614.398010253906,17.0014991760254), Vec3d(1352.18603515625,564.398986816406,20.0014991760254), Vec3d(1363.65405273438,589.398986816406,23.3004989624023), Vec3d(1359.46704101562,589.398986816406,23.3004989624023), Vec3d(1358.37109375,564.398986816406,23.3004989624023), Vec3d(1385.56103515625,564.398986816406,23.3004989624023), Vec3d(1373.06311035156,589.398986816406,23.3004989624023), Vec3d(1368.80810546875,564.398986816406,23.3004989624023), Vec3d(1387.623046875,589.398986816406,23.3004989624023), Vec3d(1387.623046875,585.276000976562,23.3004989624023), Vec3d(1389.68505859375,589.398986816406,23.3004989624023), Vec3d(1389.68505859375,572.64599609375,23.3004989624023), Vec3d(1389.68505859375,564.398986816406,23.3004989624023), Vec3d(1367.77709960938,589.398986816406,23.3004989624023), Vec3d(1366.7470703125,564.398986816406,23.3004989624023), Vec3d(1354.31201171875,589.398986816406,23.3004989624023), Vec3d(1352.18603515625,564.398986816406,23.3004989624023), Vec3d(1389.68505859375,614.398010253906,23.3004989624023), Vec3d(1377.31701660156,614.398010253906,23.3004989624023), Vec3d(1381.43908691406,589.398986816406,23.3004989624023), Vec3d(1368.80700683594,614.398010253906,23.3004989624023), Vec3d(1368.80810546875,589.398986816406,23.3004989624023), Vec3d(1356.43908691406,614.398010253906,23.3004989624023), Vec3d(1357.40502929688,589.398986816406,23.3004989624023), Vec3d(1360.56201171875,614.398010253906,23.3004989624023), Vec3d(1348.705078125,614.398010253906,23.3004989624023), Vec3d(1350.44506835938,589.398986816406,23.3004989624023), Vec3d(1389.68505859375,606.153015136719,23.3004989624023), Vec3d(1347.35205078125,589.398986816406,23.3004989624023), Vec3d(1346.56005859375,589.398986816406,23.3004989624023), Vec3d(1346.56005859375,594.159912109375,17.0014991760254), Vec3d(1346.56005859375,589.398986816406,17.0014991760254), Vec3d(1346.56005859375,605.250427246094,23.3004989624023), Vec3d(1346.56005859375,614.398010253906,23.3004989624023), Vec3d(1346.56005859375,614.398010253906,20.8258285522461), Vec3d(1346.56005859375,614.398010253906,17.0014991760254), Vec3d(1346.56005859375,564.398986816406,19.10133934021), Vec3d(1346.56005859375,567.548583984375,23.3004989624023), Vec3d(1346.56005859375,564.398986816406,17.0020332336426), Vec3d(1346.56005859375,564.398986816406,23.0018501281738), Vec3d(1346.56005859375,564.398986816406,23.3004989624023), Vec3d(1346.56005859375,575.118957519531,17.0014991760254), Vec3d(1346.56005859375,574.754028320312,23.3004989624023) + vertices = std::vector{ + Vec3f(1364.68505859375,614.398010253906,20.002498626709), Vec3f(1389.68505859375,614.398010253906,20.002498626709), Vec3f(1377.18505859375,589.398986816406,20.002498626709), Vec3f(1389.68505859375,589.398986816406,20.002498626709), Vec3f(1389.68505859375,564.398986816406,20.0014991760254), Vec3f(1364.68505859375,589.398986816406,20.002498626709), Vec3f(1364.68505859375,564.398986816406,20.0014991760254), Vec3f(1360.93505859375,589.398986816406,17.0014991760254), Vec3f(1360.93505859375,585.64697265625,17.0014991760254), Vec3f(1357.18505859375,564.398986816406,17.0014991760254), Vec3f(1364.68505859375,589.398986816406,17.0014991760254), Vec3f(1364.68505859375,571.899963378906,17.0014991760254), Vec3f(1364.68505859375,564.398986816406,17.0014991760254), Vec3f(1348.43603515625,564.398986816406,17.0014991760254), Vec3f(1352.80908203125,589.398986816406,17.0014991760254), Vec3f(1357.18408203125,589.398986816406,17.0014991760254), Vec3f(1357.18310546875,614.398010253906,17.0014991760254), Vec3f(1364.68505859375,606.89599609375,17.0014991760254), Vec3f(1364.68505859375,614.398010253906,17.0014991760254), Vec3f(1352.18603515625,564.398986816406,20.0014991760254), Vec3f(1363.65405273438,589.398986816406,23.3004989624023), Vec3f(1359.46704101562,589.398986816406,23.3004989624023), Vec3f(1358.37109375,564.398986816406,23.3004989624023), Vec3f(1385.56103515625,564.398986816406,23.3004989624023), Vec3f(1373.06311035156,589.398986816406,23.3004989624023), Vec3f(1368.80810546875,564.398986816406,23.3004989624023), Vec3f(1387.623046875,589.398986816406,23.3004989624023), Vec3f(1387.623046875,585.276000976562,23.3004989624023), Vec3f(1389.68505859375,589.398986816406,23.3004989624023), Vec3f(1389.68505859375,572.64599609375,23.3004989624023), Vec3f(1389.68505859375,564.398986816406,23.3004989624023), Vec3f(1367.77709960938,589.398986816406,23.3004989624023), Vec3f(1366.7470703125,564.398986816406,23.3004989624023), Vec3f(1354.31201171875,589.398986816406,23.3004989624023), Vec3f(1352.18603515625,564.398986816406,23.3004989624023), Vec3f(1389.68505859375,614.398010253906,23.3004989624023), Vec3f(1377.31701660156,614.398010253906,23.3004989624023), Vec3f(1381.43908691406,589.398986816406,23.3004989624023), Vec3f(1368.80700683594,614.398010253906,23.3004989624023), Vec3f(1368.80810546875,589.398986816406,23.3004989624023), Vec3f(1356.43908691406,614.398010253906,23.3004989624023), Vec3f(1357.40502929688,589.398986816406,23.3004989624023), Vec3f(1360.56201171875,614.398010253906,23.3004989624023), Vec3f(1348.705078125,614.398010253906,23.3004989624023), Vec3f(1350.44506835938,589.398986816406,23.3004989624023), Vec3f(1389.68505859375,606.153015136719,23.3004989624023), Vec3f(1347.35205078125,589.398986816406,23.3004989624023), Vec3f(1346.56005859375,589.398986816406,23.3004989624023), Vec3f(1346.56005859375,594.159912109375,17.0014991760254), Vec3f(1346.56005859375,589.398986816406,17.0014991760254), Vec3f(1346.56005859375,605.250427246094,23.3004989624023), Vec3f(1346.56005859375,614.398010253906,23.3004989624023), Vec3f(1346.56005859375,614.398010253906,20.8258285522461), Vec3f(1346.56005859375,614.398010253906,17.0014991760254), Vec3f(1346.56005859375,564.398986816406,19.10133934021), Vec3f(1346.56005859375,567.548583984375,23.3004989624023), Vec3f(1346.56005859375,564.398986816406,17.0020332336426), Vec3f(1346.56005859375,564.398986816406,23.0018501281738), Vec3f(1346.56005859375,564.398986816406,23.3004989624023), Vec3f(1346.56005859375,575.118957519531,17.0014991760254), Vec3f(1346.56005859375,574.754028320312,23.3004989624023) }; facets = std::vector{ Vec3i32(0,1,2), Vec3i32(2,3,4), Vec3i32(2,5,0), Vec3i32(4,6,2), Vec3i32(2,6,5), Vec3i32(2,1,3), Vec3i32(7,8,9), Vec3i32(10,9,8), Vec3i32(11,9,10), Vec3i32(12,9,11), Vec3i32(9,13,14), Vec3i32(7,15,16), Vec3i32(10,17,0), Vec3i32(10,0,5), Vec3i32(12,11,6), Vec3i32(18,16,0), Vec3i32(6,19,13), Vec3i32(6,13,9), Vec3i32(9,12,6), Vec3i32(17,18,0), Vec3i32(11,10,5), Vec3i32(11,5,6), Vec3i32(14,16,15), Vec3i32(17,7,18), Vec3i32(16,18,7), Vec3i32(14,15,9), Vec3i32(7,9,15), Vec3i32(7,17,8), Vec3i32(10,8,17), Vec3i32(20,21,22), Vec3i32(23,24,25), Vec3i32(26,23,27), Vec3i32(28,27,23), Vec3i32(29,28,23), Vec3i32(30,29,23), Vec3i32(25,31,32), Vec3i32(22,33,34), Vec3i32(35,36,37), Vec3i32(24,38,39), Vec3i32(21,40,41), Vec3i32(38,42,20), Vec3i32(33,43,44), Vec3i32(6,4,23), Vec3i32(6,23,25), Vec3i32(36,35,1), Vec3i32(1,0,38), Vec3i32(1,38,36), Vec3i32(29,30,4), Vec3i32(25,32,6), Vec3i32(40,42,0), Vec3i32(35,45,1), Vec3i32(4,3,28), Vec3i32(4,28,29), Vec3i32(3,1,45), Vec3i32(3,45,28), Vec3i32(22,34,19), Vec3i32(19,6,32), Vec3i32(19,32,22), Vec3i32(42,38,0), Vec3i32(30,23,4), Vec3i32(0,16,43), Vec3i32(0,43,40), Vec3i32(24,37,36), Vec3i32(38,24,36), Vec3i32(24,23,37), Vec3i32(37,23,26), Vec3i32(22,32,20), Vec3i32(20,32,31), Vec3i32(33,41,40), Vec3i32(43,33,40), Vec3i32(45,35,26), Vec3i32(37,26,35), Vec3i32(33,44,34), Vec3i32(44,43,46), Vec3i32(20,42,21), Vec3i32(40,21,42), Vec3i32(31,39,38), Vec3i32(20,31,38), Vec3i32(33,22,41), Vec3i32(21,41,22), Vec3i32(31,25,39), Vec3i32(24,39,25), Vec3i32(26,27,45), Vec3i32(28,45,27), Vec3i32(47,48,49), Vec3i32(47,50,48), Vec3i32(51,48,50), Vec3i32(52,48,51), Vec3i32(53,48,52), Vec3i32(54,55,56), Vec3i32(57,55,54), Vec3i32(58,55,57), Vec3i32(49,59,47), Vec3i32(60,56,55), Vec3i32(59,56,60), Vec3i32(60,47,59), Vec3i32(48,53,16), Vec3i32(56,13,19), Vec3i32(54,56,19), Vec3i32(56,59,13), Vec3i32(59,49,14), Vec3i32(59,14,13), Vec3i32(49,48,16), Vec3i32(49,16,14), Vec3i32(44,46,60), Vec3i32(44,60,55), Vec3i32(51,50,43), Vec3i32(19,34,58), Vec3i32(19,58,57), Vec3i32(53,52,16), Vec3i32(43,16,52), Vec3i32(43,52,51), Vec3i32(57,54,19), Vec3i32(47,60,46), Vec3i32(55,58,34), Vec3i32(55,34,44), Vec3i32(50,47,46), Vec3i32(50,46,43) }; break; case TestMesh::_40x10: - vertices = std::vector{ - Vec3d(12.8680295944214,29.5799007415771,12), Vec3d(11.7364797592163,29.8480796813965,12), Vec3d(11.1571502685547,29.5300102233887,12), Vec3d(10.5814504623413,29.9830799102783,12), Vec3d(10,29.6000003814697,12), Vec3d(9.41855144500732,29.9830799102783,12), Vec3d(8.84284687042236,29.5300102233887,12), Vec3d(8.26351833343506,29.8480796813965,12), Vec3d(7.70256900787354,29.3210391998291,12), Vec3d(7.13196802139282,29.5799007415771,12), Vec3d(6.59579277038574,28.9761600494385,12), Vec3d(6.03920221328735,29.1821594238281,12), Vec3d(5.53865718841553,28.5003795623779,12), Vec3d(5,28.6602592468262,12), Vec3d(4.54657793045044,27.9006500244141,12), Vec3d(4.02841377258301,28.0212306976318,12), Vec3d(3.63402199745178,27.1856994628906,12), Vec3d(3.13758301734924,27.2737407684326,12), Vec3d(2.81429696083069,26.3659801483154,12), Vec3d(2.33955597877502,26.4278793334961,12), Vec3d(2.0993549823761,25.4534206390381,12), Vec3d(1.64512205123901,25.4950904846191,12), Vec3d(1.49962198734283,24.4613399505615,12), Vec3d(1.0636739730835,24.4879894256592,12), Vec3d(1.02384400367737,23.4042091369629,12), Vec3d(0.603073298931122,23.4202003479004,12), Vec3d(0.678958415985107,22.2974300384521,12), Vec3d(0.269550800323486,22.3061599731445,12), Vec3d(0.469994693994522,21.1571502685547,12), Vec3d(0.067615881562233,21.1609306335449,12), Vec3d(0.399999290704727,20,12), Vec3d(0,20,12), Vec3d(0.399999290704727,5,12), Vec3d(0,5,12), Vec3d(0.456633001565933,4.2804012298584,12), Vec3d(0.0615576282143593,4.21782684326172,12), Vec3d(0.625140011310577,3.5785219669342,12), Vec3d(0.244717106223106,3.45491504669189,12), Vec3d(0.901369392871857,2.91164398193359,12), Vec3d(0.544967114925385,2.73004698753357,12), Vec3d(1.27852201461792,2.29618692398071,12), Vec3d(0.954914808273315,2.06107401847839,12), Vec3d(1.74730801582336,1.74730801582336,12), Vec3d(1.46446597576141,1.46446597576141,12), Vec3d(2.29618692398071,1.27852201461792,12), Vec3d(2.06107401847839,0.954914808273315,12), Vec3d(2.91164398193359,0.901369392871857,12), Vec3d(2.73004698753357,0.544967114925385,12), Vec3d(3.5785219669342,0.625140011310577,12), Vec3d(3.45491504669189,0.244717106223106,12), Vec3d(4.2804012298584,0.456633001565933,12), Vec3d(4.21782684326172,0.0615576282143593,12), Vec3d(5,0.399999290704727,12), Vec3d(5,0,12), Vec3d(19.6000003814697,0.399999290704727,12), Vec3d(20,0,12), Vec3d(19.6000003814697,20,12), Vec3d(20,20,12), Vec3d(19.5300102233887,21.1571502685547,12), Vec3d(19.9323806762695,21.1609306335449,12), Vec3d(19.3210391998291,22.2974300384521,12), Vec3d(19.7304496765137,22.3061599731445,12), Vec3d(18.9761600494385,23.4042091369629,12), Vec3d(19.3969306945801,23.4202003479004,12), Vec3d(18.5003795623779,24.4613399505615,12), Vec3d(18.9363307952881,24.4879894256592,12), Vec3d(17.9006500244141,25.4534206390381,12), Vec3d(18.3548793792725,25.4950904846191,12), Vec3d(17.1856994628906,26.3659801483154,12), Vec3d(17.6604404449463,26.4278793334961,12), Vec3d(16.3659801483154,27.1856994628906,12), Vec3d(16.862419128418,27.2737407684326,12), Vec3d(15.4534196853638,27.9006500244141,12), Vec3d(15.9715900421143,28.0212306976318,12), Vec3d(14.4613399505615,28.5003795623779,12), Vec3d(15,28.6602592468262,12), Vec3d(13.4042100906372,28.9761600494385,12), Vec3d(13.9608001708984,29.1821594238281,12), Vec3d(12.2974300384521,29.3210391998291,12), Vec3d(7.13196802139282,29.5799007415771,0), Vec3d(8.26351833343506,29.8480796813965,0), Vec3d(8.84284687042236,29.5300102233887,0), Vec3d(9.41855144500732,29.9830799102783,0), Vec3d(10,29.6000003814697,0), Vec3d(10.5814504623413,29.9830799102783,0), Vec3d(11.1571502685547,29.5300102233887,0), Vec3d(11.7364797592163,29.8480796813965,0), Vec3d(12.2974300384521,29.3210391998291,0), Vec3d(12.8680295944214,29.5799007415771,0), Vec3d(13.4042100906372,28.9761600494385,0), Vec3d(13.9608001708984,29.1821594238281,0), Vec3d(14.4613399505615,28.5003795623779,0), Vec3d(15,28.6602592468262,0), Vec3d(15.4534196853638,27.9006500244141,0), Vec3d(15.9715900421143,28.0212306976318,0), Vec3d(16.3659801483154,27.1856994628906,0), Vec3d(16.862419128418,27.2737407684326,0), Vec3d(17.1856994628906,26.3659801483154,0), Vec3d(17.6604404449463,26.4278793334961,0), Vec3d(17.9006500244141,25.4534206390381,0), Vec3d(18.3548793792725,25.4950904846191,0), Vec3d(18.5003795623779,24.4613399505615,0), Vec3d(18.9363307952881,24.4879894256592,0), Vec3d(18.9761600494385,23.4042091369629,0), Vec3d(19.3969306945801,23.4202003479004,0), Vec3d(19.3210391998291,22.2974300384521,0), Vec3d(19.7304496765137,22.3061599731445,0), Vec3d(19.5300102233887,21.1571502685547,0), Vec3d(19.9323806762695,21.1609306335449,0), Vec3d(19.6000003814697,20,0), Vec3d(20,20,0), Vec3d(19.6000003814697,0.399999290704727,0), Vec3d(20,0,0), Vec3d(5,0.399999290704727,0), Vec3d(5,0,0), Vec3d(4.2804012298584,0.456633001565933,0), Vec3d(4.21782684326172,0.0615576282143593,0), Vec3d(3.5785219669342,0.625140011310577,0), Vec3d(3.45491504669189,0.244717106223106,0), Vec3d(2.91164398193359,0.901369392871857,0), Vec3d(2.73004698753357,0.544967114925385,0), Vec3d(2.29618692398071,1.27852201461792,0), Vec3d(2.06107401847839,0.954914808273315,0), Vec3d(1.74730801582336,1.74730801582336,0), Vec3d(1.46446597576141,1.46446597576141,0), Vec3d(1.27852201461792,2.29618692398071,0), Vec3d(0.954914808273315,2.06107401847839,0), Vec3d(0.901369392871857,2.91164398193359,0), Vec3d(0.544967114925385,2.73004698753357,0), Vec3d(0.625140011310577,3.5785219669342,0), Vec3d(0.244717106223106,3.45491504669189,0), Vec3d(0.456633001565933,4.2804012298584,0), Vec3d(0.0615576282143593,4.21782684326172,0), Vec3d(0.399999290704727,5,0), Vec3d(0,5,0), Vec3d(0.399999290704727,20,0), Vec3d(0,20,0), Vec3d(0.469994693994522,21.1571502685547,0), Vec3d(0.067615881562233,21.1609306335449,0), Vec3d(0.678958415985107,22.2974300384521,0), Vec3d(0.269550800323486,22.3061599731445,0), Vec3d(1.02384400367737,23.4042091369629,0), Vec3d(0.603073298931122,23.4202003479004,0), Vec3d(1.49962198734283,24.4613399505615,0), Vec3d(1.0636739730835,24.4879894256592,0), Vec3d(2.0993549823761,25.4534206390381,0), Vec3d(1.64512205123901,25.4950904846191,0), Vec3d(2.81429696083069,26.3659801483154,0), Vec3d(2.33955597877502,26.4278793334961,0), Vec3d(3.63402199745178,27.1856994628906,0), Vec3d(3.13758301734924,27.2737407684326,0), Vec3d(4.54657793045044,27.9006500244141,0), Vec3d(4.02841377258301,28.0212306976318,0), Vec3d(5.53865718841553,28.5003795623779,0), Vec3d(5,28.6602592468262,0), Vec3d(6.59579277038574,28.9761600494385,0), Vec3d(6.03920221328735,29.1821594238281,0), Vec3d(7.70256900787354,29.3210391998291,0) + vertices = std::vector{ + Vec3f(12.8680295944214,29.5799007415771,12), Vec3f(11.7364797592163,29.8480796813965,12), Vec3f(11.1571502685547,29.5300102233887,12), Vec3f(10.5814504623413,29.9830799102783,12), Vec3f(10,29.6000003814697,12), Vec3f(9.41855144500732,29.9830799102783,12), Vec3f(8.84284687042236,29.5300102233887,12), Vec3f(8.26351833343506,29.8480796813965,12), Vec3f(7.70256900787354,29.3210391998291,12), Vec3f(7.13196802139282,29.5799007415771,12), Vec3f(6.59579277038574,28.9761600494385,12), Vec3f(6.03920221328735,29.1821594238281,12), Vec3f(5.53865718841553,28.5003795623779,12), Vec3f(5,28.6602592468262,12), Vec3f(4.54657793045044,27.9006500244141,12), Vec3f(4.02841377258301,28.0212306976318,12), Vec3f(3.63402199745178,27.1856994628906,12), Vec3f(3.13758301734924,27.2737407684326,12), Vec3f(2.81429696083069,26.3659801483154,12), Vec3f(2.33955597877502,26.4278793334961,12), Vec3f(2.0993549823761,25.4534206390381,12), Vec3f(1.64512205123901,25.4950904846191,12), Vec3f(1.49962198734283,24.4613399505615,12), Vec3f(1.0636739730835,24.4879894256592,12), Vec3f(1.02384400367737,23.4042091369629,12), Vec3f(0.603073298931122,23.4202003479004,12), Vec3f(0.678958415985107,22.2974300384521,12), Vec3f(0.269550800323486,22.3061599731445,12), Vec3f(0.469994693994522,21.1571502685547,12), Vec3f(0.067615881562233,21.1609306335449,12), Vec3f(0.399999290704727,20,12), Vec3f(0,20,12), Vec3f(0.399999290704727,5,12), Vec3f(0,5,12), Vec3f(0.456633001565933,4.2804012298584,12), Vec3f(0.0615576282143593,4.21782684326172,12), Vec3f(0.625140011310577,3.5785219669342,12), Vec3f(0.244717106223106,3.45491504669189,12), Vec3f(0.901369392871857,2.91164398193359,12), Vec3f(0.544967114925385,2.73004698753357,12), Vec3f(1.27852201461792,2.29618692398071,12), Vec3f(0.954914808273315,2.06107401847839,12), Vec3f(1.74730801582336,1.74730801582336,12), Vec3f(1.46446597576141,1.46446597576141,12), Vec3f(2.29618692398071,1.27852201461792,12), Vec3f(2.06107401847839,0.954914808273315,12), Vec3f(2.91164398193359,0.901369392871857,12), Vec3f(2.73004698753357,0.544967114925385,12), Vec3f(3.5785219669342,0.625140011310577,12), Vec3f(3.45491504669189,0.244717106223106,12), Vec3f(4.2804012298584,0.456633001565933,12), Vec3f(4.21782684326172,0.0615576282143593,12), Vec3f(5,0.399999290704727,12), Vec3f(5,0,12), Vec3f(19.6000003814697,0.399999290704727,12), Vec3f(20,0,12), Vec3f(19.6000003814697,20,12), Vec3f(20,20,12), Vec3f(19.5300102233887,21.1571502685547,12), Vec3f(19.9323806762695,21.1609306335449,12), Vec3f(19.3210391998291,22.2974300384521,12), Vec3f(19.7304496765137,22.3061599731445,12), Vec3f(18.9761600494385,23.4042091369629,12), Vec3f(19.3969306945801,23.4202003479004,12), Vec3f(18.5003795623779,24.4613399505615,12), Vec3f(18.9363307952881,24.4879894256592,12), Vec3f(17.9006500244141,25.4534206390381,12), Vec3f(18.3548793792725,25.4950904846191,12), Vec3f(17.1856994628906,26.3659801483154,12), Vec3f(17.6604404449463,26.4278793334961,12), Vec3f(16.3659801483154,27.1856994628906,12), Vec3f(16.862419128418,27.2737407684326,12), Vec3f(15.4534196853638,27.9006500244141,12), Vec3f(15.9715900421143,28.0212306976318,12), Vec3f(14.4613399505615,28.5003795623779,12), Vec3f(15,28.6602592468262,12), Vec3f(13.4042100906372,28.9761600494385,12), Vec3f(13.9608001708984,29.1821594238281,12), Vec3f(12.2974300384521,29.3210391998291,12), Vec3f(7.13196802139282,29.5799007415771,0), Vec3f(8.26351833343506,29.8480796813965,0), Vec3f(8.84284687042236,29.5300102233887,0), Vec3f(9.41855144500732,29.9830799102783,0), Vec3f(10,29.6000003814697,0), Vec3f(10.5814504623413,29.9830799102783,0), Vec3f(11.1571502685547,29.5300102233887,0), Vec3f(11.7364797592163,29.8480796813965,0), Vec3f(12.2974300384521,29.3210391998291,0), Vec3f(12.8680295944214,29.5799007415771,0), Vec3f(13.4042100906372,28.9761600494385,0), Vec3f(13.9608001708984,29.1821594238281,0), Vec3f(14.4613399505615,28.5003795623779,0), Vec3f(15,28.6602592468262,0), Vec3f(15.4534196853638,27.9006500244141,0), Vec3f(15.9715900421143,28.0212306976318,0), Vec3f(16.3659801483154,27.1856994628906,0), Vec3f(16.862419128418,27.2737407684326,0), Vec3f(17.1856994628906,26.3659801483154,0), Vec3f(17.6604404449463,26.4278793334961,0), Vec3f(17.9006500244141,25.4534206390381,0), Vec3f(18.3548793792725,25.4950904846191,0), Vec3f(18.5003795623779,24.4613399505615,0), Vec3f(18.9363307952881,24.4879894256592,0), Vec3f(18.9761600494385,23.4042091369629,0), Vec3f(19.3969306945801,23.4202003479004,0), Vec3f(19.3210391998291,22.2974300384521,0), Vec3f(19.7304496765137,22.3061599731445,0), Vec3f(19.5300102233887,21.1571502685547,0), Vec3f(19.9323806762695,21.1609306335449,0), Vec3f(19.6000003814697,20,0), Vec3f(20,20,0), Vec3f(19.6000003814697,0.399999290704727,0), Vec3f(20,0,0), Vec3f(5,0.399999290704727,0), Vec3f(5,0,0), Vec3f(4.2804012298584,0.456633001565933,0), Vec3f(4.21782684326172,0.0615576282143593,0), Vec3f(3.5785219669342,0.625140011310577,0), Vec3f(3.45491504669189,0.244717106223106,0), Vec3f(2.91164398193359,0.901369392871857,0), Vec3f(2.73004698753357,0.544967114925385,0), Vec3f(2.29618692398071,1.27852201461792,0), Vec3f(2.06107401847839,0.954914808273315,0), Vec3f(1.74730801582336,1.74730801582336,0), Vec3f(1.46446597576141,1.46446597576141,0), Vec3f(1.27852201461792,2.29618692398071,0), Vec3f(0.954914808273315,2.06107401847839,0), Vec3f(0.901369392871857,2.91164398193359,0), Vec3f(0.544967114925385,2.73004698753357,0), Vec3f(0.625140011310577,3.5785219669342,0), Vec3f(0.244717106223106,3.45491504669189,0), Vec3f(0.456633001565933,4.2804012298584,0), Vec3f(0.0615576282143593,4.21782684326172,0), Vec3f(0.399999290704727,5,0), Vec3f(0,5,0), Vec3f(0.399999290704727,20,0), Vec3f(0,20,0), Vec3f(0.469994693994522,21.1571502685547,0), Vec3f(0.067615881562233,21.1609306335449,0), Vec3f(0.678958415985107,22.2974300384521,0), Vec3f(0.269550800323486,22.3061599731445,0), Vec3f(1.02384400367737,23.4042091369629,0), Vec3f(0.603073298931122,23.4202003479004,0), Vec3f(1.49962198734283,24.4613399505615,0), Vec3f(1.0636739730835,24.4879894256592,0), Vec3f(2.0993549823761,25.4534206390381,0), Vec3f(1.64512205123901,25.4950904846191,0), Vec3f(2.81429696083069,26.3659801483154,0), Vec3f(2.33955597877502,26.4278793334961,0), Vec3f(3.63402199745178,27.1856994628906,0), Vec3f(3.13758301734924,27.2737407684326,0), Vec3f(4.54657793045044,27.9006500244141,0), Vec3f(4.02841377258301,28.0212306976318,0), Vec3f(5.53865718841553,28.5003795623779,0), Vec3f(5,28.6602592468262,0), Vec3f(6.59579277038574,28.9761600494385,0), Vec3f(6.03920221328735,29.1821594238281,0), Vec3f(7.70256900787354,29.3210391998291,0) }; facets = std::vector{ Vec3i32(0,1,2), Vec3i32(2,1,3), Vec3i32(2,3,4), Vec3i32(4,3,5), Vec3i32(4,5,6), Vec3i32(6,5,7), Vec3i32(6,7,8), Vec3i32(8,7,9), Vec3i32(8,9,10), Vec3i32(10,9,11), Vec3i32(10,11,12), Vec3i32(12,11,13), Vec3i32(12,13,14), Vec3i32(14,13,15), Vec3i32(14,15,16), Vec3i32(16,15,17), Vec3i32(16,17,18), Vec3i32(18,17,19), Vec3i32(18,19,20), Vec3i32(20,19,21), Vec3i32(20,21,22), Vec3i32(22,21,23), Vec3i32(22,23,24), Vec3i32(24,23,25), Vec3i32(24,25,26), Vec3i32(26,25,27), Vec3i32(26,27,28), Vec3i32(28,27,29), Vec3i32(28,29,30), Vec3i32(30,29,31), Vec3i32(30,31,32), Vec3i32(32,31,33), Vec3i32(32,33,34), Vec3i32(34,33,35), Vec3i32(34,35,36), Vec3i32(36,35,37), Vec3i32(36,37,38), Vec3i32(38,37,39), Vec3i32(38,39,40), Vec3i32(40,39,41), Vec3i32(40,41,42), Vec3i32(42,41,43), Vec3i32(42,43,44), Vec3i32(44,43,45), Vec3i32(44,45,46), Vec3i32(46,45,47), Vec3i32(46,47,48), Vec3i32(48,47,49), Vec3i32(48,49,50), Vec3i32(50,49,51), Vec3i32(50,51,52), Vec3i32(52,51,53), Vec3i32(52,53,54), Vec3i32(54,53,55), Vec3i32(54,55,56), Vec3i32(56,55,57), Vec3i32(56,57,58), Vec3i32(58,57,59), Vec3i32(58,59,60), Vec3i32(60,59,61), Vec3i32(60,61,62), Vec3i32(62,61,63), Vec3i32(62,63,64), Vec3i32(64,63,65), Vec3i32(64,65,66), Vec3i32(66,65,67), Vec3i32(66,67,68), Vec3i32(68,67,69), Vec3i32(68,69,70), Vec3i32(70,69,71), Vec3i32(70,71,72), Vec3i32(72,71,73), Vec3i32(72,73,74), Vec3i32(74,73,75), Vec3i32(74,75,76), Vec3i32(76,75,77), Vec3i32(76,77,78), Vec3i32(78,77,0), Vec3i32(78,0,2), Vec3i32(79,80,81), Vec3i32(81,80,82), Vec3i32(81,82,83), Vec3i32(83,82,84), Vec3i32(83,84,85), Vec3i32(85,84,86), Vec3i32(85,86,87), Vec3i32(87,86,88), Vec3i32(87,88,89), Vec3i32(89,88,90), Vec3i32(89,90,91), Vec3i32(91,90,92), Vec3i32(91,92,93), Vec3i32(93,92,94), Vec3i32(93,94,95), Vec3i32(95,94,96), Vec3i32(95,96,97), Vec3i32(97,96,98), Vec3i32(97,98,99), Vec3i32(99,98,100), Vec3i32(99,100,101), Vec3i32(101,100,102), Vec3i32(101,102,103), Vec3i32(103,102,104), Vec3i32(103,104,105), Vec3i32(105,104,106), Vec3i32(105,106,107), Vec3i32(107,106,108), Vec3i32(107,108,109), Vec3i32(109,108,110), Vec3i32(109,110,111), Vec3i32(111,110,112), Vec3i32(111,112,113), Vec3i32(113,112,114), Vec3i32(113,114,115), Vec3i32(115,114,116), Vec3i32(115,116,117), Vec3i32(117,116,118), Vec3i32(117,118,119), Vec3i32(119,118,120), Vec3i32(119,120,121), Vec3i32(121,120,122), Vec3i32(121,122,123), Vec3i32(123,122,124), Vec3i32(123,124,125), Vec3i32(125,124,126), Vec3i32(125,126,127), Vec3i32(127,126,128), Vec3i32(127,128,129), Vec3i32(129,128,130), Vec3i32(129,130,131), Vec3i32(131,130,132), Vec3i32(131,132,133), Vec3i32(133,132,134), Vec3i32(133,134,135), Vec3i32(135,134,136), Vec3i32(135,136,137), Vec3i32(137,136,138), Vec3i32(137,138,139), Vec3i32(139,138,140), Vec3i32(139,140,141), Vec3i32(141,140,142), Vec3i32(141,142,143), Vec3i32(143,142,144), Vec3i32(143,144,145), Vec3i32(145,144,146), Vec3i32(145,146,147), Vec3i32(147,146,148), Vec3i32(147,148,149), Vec3i32(149,148,150), Vec3i32(149,150,151), Vec3i32(151,150,152), Vec3i32(151,152,153), Vec3i32(153,152,154), Vec3i32(153,154,155), Vec3i32(155,154,156), Vec3i32(155,156,157), Vec3i32(157,156,79), Vec3i32(157,79,81), Vec3i32(57,110,108), Vec3i32(57,108,59), Vec3i32(59,108,106), Vec3i32(59,106,61), Vec3i32(61,106,104), Vec3i32(61,104,63), Vec3i32(63,104,102), Vec3i32(63,102,65), Vec3i32(65,102,100), Vec3i32(65,100,67), Vec3i32(67,100,98), Vec3i32(67,98,69), Vec3i32(69,98,96), Vec3i32(69,96,71), Vec3i32(71,96,94), Vec3i32(71,94,73), Vec3i32(73,94,92), Vec3i32(73,92,75), Vec3i32(75,92,90), Vec3i32(75,90,77), Vec3i32(77,90,88), Vec3i32(77,88,0), Vec3i32(0,88,86), Vec3i32(0,86,1), Vec3i32(1,86,84), Vec3i32(1,84,3), Vec3i32(3,84,82), Vec3i32(3,82,5), Vec3i32(5,82,80), Vec3i32(5,80,7), Vec3i32(7,80,79), Vec3i32(7,79,9), Vec3i32(9,79,156), Vec3i32(9,156,11), Vec3i32(11,156,154), Vec3i32(11,154,13), Vec3i32(13,154,152), Vec3i32(13,152,15), Vec3i32(15,152,150), Vec3i32(15,150,17), Vec3i32(17,150,148), Vec3i32(17,148,19), Vec3i32(19,148,146), Vec3i32(19,146,21), Vec3i32(21,146,144), Vec3i32(21,144,23), Vec3i32(23,144,142), Vec3i32(23,142,25), Vec3i32(25,142,140), Vec3i32(25,140,27), Vec3i32(27,140,138), Vec3i32(27,138,29), Vec3i32(29,138,136), Vec3i32(29,136,31), Vec3i32(33,31,134), Vec3i32(134,31,136), Vec3i32(33,134,132), Vec3i32(33,132,35), Vec3i32(35,132,130), Vec3i32(35,130,37), Vec3i32(37,130,128), Vec3i32(37,128,39), Vec3i32(39,128,126), Vec3i32(39,126,41), Vec3i32(41,126,124), Vec3i32(41,124,43), Vec3i32(43,124,122), Vec3i32(43,122,45), Vec3i32(45,122,120), Vec3i32(45,120,47), Vec3i32(47,120,118), Vec3i32(47,118,49), Vec3i32(49,118,116), Vec3i32(49,116,51), Vec3i32(51,116,114), Vec3i32(51,114,53), Vec3i32(55,53,112), Vec3i32(112,53,114), Vec3i32(57,55,110), Vec3i32(110,55,112), Vec3i32(30,135,137), Vec3i32(30,137,28), Vec3i32(28,137,139), Vec3i32(28,139,26), Vec3i32(26,139,141), Vec3i32(26,141,24), Vec3i32(24,141,143), Vec3i32(24,143,22), Vec3i32(22,143,145), Vec3i32(22,145,20), Vec3i32(20,145,147), Vec3i32(20,147,18), Vec3i32(18,147,149), Vec3i32(18,149,16), Vec3i32(16,149,151), Vec3i32(16,151,14), Vec3i32(14,151,153), Vec3i32(14,153,12), Vec3i32(12,153,155), Vec3i32(12,155,10), Vec3i32(10,155,157), Vec3i32(10,157,8), Vec3i32(8,157,81), Vec3i32(8,81,6), Vec3i32(6,81,83), Vec3i32(6,83,4), Vec3i32(4,83,85), Vec3i32(4,85,2), Vec3i32(2,85,87), Vec3i32(2,87,78), Vec3i32(78,87,89), Vec3i32(78,89,76), Vec3i32(76,89,91), Vec3i32(76,91,74), Vec3i32(74,91,93), Vec3i32(74,93,72), Vec3i32(72,93,95), Vec3i32(72,95,70), Vec3i32(70,95,97), Vec3i32(70,97,68), Vec3i32(68,97,99), Vec3i32(68,99,66), Vec3i32(66,99,101), Vec3i32(66,101,64), Vec3i32(64,101,103), Vec3i32(64,103,62), Vec3i32(62,103,105), Vec3i32(62,105,60), Vec3i32(60,105,107), Vec3i32(60,107,58), Vec3i32(58,107,109), Vec3i32(58,109,56), Vec3i32(30,32,135), Vec3i32(135,32,133), Vec3i32(52,113,115), Vec3i32(52,115,50), Vec3i32(50,115,117), Vec3i32(50,117,48), Vec3i32(48,117,119), Vec3i32(48,119,46), Vec3i32(46,119,121), Vec3i32(46,121,44), Vec3i32(44,121,123), Vec3i32(44,123,42), Vec3i32(42,123,125), Vec3i32(42,125,40), Vec3i32(40,125,127), Vec3i32(40,127,38), Vec3i32(38,127,129), Vec3i32(38,129,36), Vec3i32(36,129,131), Vec3i32(36,131,34), Vec3i32(34,131,133), Vec3i32(34,133,32), Vec3i32(52,54,113), Vec3i32(113,54,111), Vec3i32(54,56,111), Vec3i32(111,56,109) }; break; case TestMesh::sloping_hole: - vertices = std::vector{ - Vec3d(-20,-20,-5), Vec3d(-20,-20,5), Vec3d(-20,20,-5), Vec3d(-20,20,5), Vec3d(20,-20,-5), Vec3d(20,-20,5), Vec3d(4.46294021606445,7.43144989013672,-5), Vec3d(20,20,-5), Vec3d(-19.1420993804932,0,-5), Vec3d(-18.8330993652344,-2.07911992073059,-5), Vec3d(-17.9195003509521,-4.06736993789673,-5), Vec3d(-16.4412002563477,-5.87785005569458,-5), Vec3d(-14.4629001617432,-7.43144989013672,-5), Vec3d(-12.0711002349854,-8.66024971008301,-5), Vec3d(-9.37016010284424,-9.51056003570557,-5), Vec3d(-3.5217399597168,-9.94521999359131,-5), Vec3d(-6.4782600402832,-9.94521999359131,-5), Vec3d(-0.629840016365051,-9.51056003570557,-5), Vec3d(2.07106995582581,-8.66024971008301,-5), Vec3d(6.44122982025146,-5.87785005569458,-5), Vec3d(4.46294021606445,-7.43144989013672,-5), Vec3d(-12.0711002349854,8.66024971008301,-5), Vec3d(-9.37016010284424,9.51056003570557,-5), Vec3d(7.91947984695435,-4.06736993789673,-5), Vec3d(8.83310031890869,-2.07911992073059,-5), Vec3d(-6.4782600402832,9.94521999359131,-5), Vec3d(-0.629840016365051,9.51056003570557,-5), Vec3d(2.07106995582581,8.66024971008301,-5), Vec3d(9.14214038848877,0,-5), Vec3d(8.83310031890869,2.07911992073059,-5), Vec3d(-3.5217399597168,9.94521999359131,-5), Vec3d(7.91947984695435,4.06736993789673,-5), Vec3d(6.44122982025146,5.87785005569458,-5), Vec3d(-14.4629001617432,7.43144989013672,-5), Vec3d(-16.4412002563477,5.87785005569458,-5), Vec3d(-17.9195003509521,4.06736993789673,-5), Vec3d(-18.8330993652344,2.07911992073059,-5), Vec3d(20,20,5), Vec3d(3.5217399597168,-9.94521999359131,5), Vec3d(-8.83310031890869,-2.07911992073059,5), Vec3d(-9.14214038848877,0,5), Vec3d(-8.83310031890869,2.07911992073059,5), Vec3d(6.4782600402832,-9.94521999359131,5), Vec3d(-7.91947984695435,4.06736993789673,5), Vec3d(-6.44122982025146,5.87785005569458,5), Vec3d(-4.46294021606445,7.43144989013672,5), Vec3d(-2.07106995582581,8.66024971008301,5), Vec3d(0.629840016365051,9.51056003570557,5), Vec3d(12.0711002349854,-8.66024971008301,5), Vec3d(9.37016010284424,-9.51056003570557,5), Vec3d(3.5217399597168,9.94521999359131,5), Vec3d(6.4782600402832,9.94521999359131,5), Vec3d(9.37016010284424,9.51056003570557,5), Vec3d(12.0711002349854,8.66024971008301,5), Vec3d(14.4629001617432,7.43144989013672,5), Vec3d(16.4412002563477,-5.87785005569458,5), Vec3d(14.4629001617432,-7.43144989013672,5), Vec3d(16.4412002563477,5.87785005569458,5), Vec3d(17.9195003509521,4.06736993789673,5), Vec3d(18.8330993652344,-2.07911992073059,5), Vec3d(17.9195003509521,-4.06736993789673,5), Vec3d(18.8330993652344,2.07911992073059,5), Vec3d(19.1420993804932,0,5), Vec3d(0.629840016365051,-9.51056003570557,5), Vec3d(-2.07106995582581,-8.66024971008301,5), Vec3d(-4.46294021606445,-7.43144989013672,5), Vec3d(-6.44122982025146,-5.87785005569458,5), Vec3d(-7.91947984695435,-4.06736993789673,5) + vertices = std::vector{ + Vec3f(-20,-20,-5), Vec3f(-20,-20,5), Vec3f(-20,20,-5), Vec3f(-20,20,5), Vec3f(20,-20,-5), Vec3f(20,-20,5), Vec3f(4.46294021606445,7.43144989013672,-5), Vec3f(20,20,-5), Vec3f(-19.1420993804932,0,-5), Vec3f(-18.8330993652344,-2.07911992073059,-5), Vec3f(-17.9195003509521,-4.06736993789673,-5), Vec3f(-16.4412002563477,-5.87785005569458,-5), Vec3f(-14.4629001617432,-7.43144989013672,-5), Vec3f(-12.0711002349854,-8.66024971008301,-5), Vec3f(-9.37016010284424,-9.51056003570557,-5), Vec3f(-3.5217399597168,-9.94521999359131,-5), Vec3f(-6.4782600402832,-9.94521999359131,-5), Vec3f(-0.629840016365051,-9.51056003570557,-5), Vec3f(2.07106995582581,-8.66024971008301,-5), Vec3f(6.44122982025146,-5.87785005569458,-5), Vec3f(4.46294021606445,-7.43144989013672,-5), Vec3f(-12.0711002349854,8.66024971008301,-5), Vec3f(-9.37016010284424,9.51056003570557,-5), Vec3f(7.91947984695435,-4.06736993789673,-5), Vec3f(8.83310031890869,-2.07911992073059,-5), Vec3f(-6.4782600402832,9.94521999359131,-5), Vec3f(-0.629840016365051,9.51056003570557,-5), Vec3f(2.07106995582581,8.66024971008301,-5), Vec3f(9.14214038848877,0,-5), Vec3f(8.83310031890869,2.07911992073059,-5), Vec3f(-3.5217399597168,9.94521999359131,-5), Vec3f(7.91947984695435,4.06736993789673,-5), Vec3f(6.44122982025146,5.87785005569458,-5), Vec3f(-14.4629001617432,7.43144989013672,-5), Vec3f(-16.4412002563477,5.87785005569458,-5), Vec3f(-17.9195003509521,4.06736993789673,-5), Vec3f(-18.8330993652344,2.07911992073059,-5), Vec3f(20,20,5), Vec3f(3.5217399597168,-9.94521999359131,5), Vec3f(-8.83310031890869,-2.07911992073059,5), Vec3f(-9.14214038848877,0,5), Vec3f(-8.83310031890869,2.07911992073059,5), Vec3f(6.4782600402832,-9.94521999359131,5), Vec3f(-7.91947984695435,4.06736993789673,5), Vec3f(-6.44122982025146,5.87785005569458,5), Vec3f(-4.46294021606445,7.43144989013672,5), Vec3f(-2.07106995582581,8.66024971008301,5), Vec3f(0.629840016365051,9.51056003570557,5), Vec3f(12.0711002349854,-8.66024971008301,5), Vec3f(9.37016010284424,-9.51056003570557,5), Vec3f(3.5217399597168,9.94521999359131,5), Vec3f(6.4782600402832,9.94521999359131,5), Vec3f(9.37016010284424,9.51056003570557,5), Vec3f(12.0711002349854,8.66024971008301,5), Vec3f(14.4629001617432,7.43144989013672,5), Vec3f(16.4412002563477,-5.87785005569458,5), Vec3f(14.4629001617432,-7.43144989013672,5), Vec3f(16.4412002563477,5.87785005569458,5), Vec3f(17.9195003509521,4.06736993789673,5), Vec3f(18.8330993652344,-2.07911992073059,5), Vec3f(17.9195003509521,-4.06736993789673,5), Vec3f(18.8330993652344,2.07911992073059,5), Vec3f(19.1420993804932,0,5), Vec3f(0.629840016365051,-9.51056003570557,5), Vec3f(-2.07106995582581,-8.66024971008301,5), Vec3f(-4.46294021606445,-7.43144989013672,5), Vec3f(-6.44122982025146,-5.87785005569458,5), Vec3f(-7.91947984695435,-4.06736993789673,5) }; facets = std::vector{ Vec3i32(0,1,2), Vec3i32(2,1,3), Vec3i32(1,0,4), Vec3i32(5,1,4), Vec3i32(6,2,7), Vec3i32(0,2,8), Vec3i32(0,8,9), Vec3i32(0,9,10), Vec3i32(0,10,11), Vec3i32(0,11,12), Vec3i32(0,12,13), Vec3i32(0,13,4), Vec3i32(13,14,4), Vec3i32(15,4,16), Vec3i32(17,4,15), Vec3i32(18,4,17), Vec3i32(19,4,20), Vec3i32(18,20,4), Vec3i32(21,2,22), Vec3i32(4,19,23), Vec3i32(4,23,7), Vec3i32(23,24,7), Vec3i32(22,2,25), Vec3i32(26,2,27), Vec3i32(28,29,7), Vec3i32(25,2,30), Vec3i32(29,31,7), Vec3i32(30,2,26), Vec3i32(31,32,7), Vec3i32(27,2,6), Vec3i32(32,6,7), Vec3i32(28,7,24), Vec3i32(33,2,21), Vec3i32(34,2,33), Vec3i32(35,2,34), Vec3i32(36,2,35), Vec3i32(8,2,36), Vec3i32(16,4,14), Vec3i32(2,3,7), Vec3i32(7,3,37), Vec3i32(38,1,5), Vec3i32(3,1,39), Vec3i32(3,39,40), Vec3i32(3,40,41), Vec3i32(42,38,5), Vec3i32(3,41,43), Vec3i32(3,43,44), Vec3i32(37,3,45), Vec3i32(37,45,46), Vec3i32(37,46,47), Vec3i32(48,49,5), Vec3i32(37,47,50), Vec3i32(49,42,5), Vec3i32(37,50,51), Vec3i32(37,51,52), Vec3i32(37,52,53), Vec3i32(37,53,54), Vec3i32(55,56,5), Vec3i32(37,54,57), Vec3i32(37,57,58), Vec3i32(59,60,5), Vec3i32(37,58,61), Vec3i32(37,62,5), Vec3i32(37,61,62), Vec3i32(62,59,5), Vec3i32(60,55,5), Vec3i32(63,1,38), Vec3i32(64,1,63), Vec3i32(65,1,64), Vec3i32(66,1,65), Vec3i32(67,1,66), Vec3i32(39,1,67), Vec3i32(44,45,3), Vec3i32(56,48,5), Vec3i32(5,4,7), Vec3i32(37,5,7), Vec3i32(41,40,36), Vec3i32(36,40,8), Vec3i32(39,9,40), Vec3i32(40,9,8), Vec3i32(43,41,35), Vec3i32(35,41,36), Vec3i32(44,43,34), Vec3i32(34,43,35), Vec3i32(33,45,44), Vec3i32(34,33,44), Vec3i32(21,46,45), Vec3i32(33,21,45), Vec3i32(22,47,46), Vec3i32(21,22,46), Vec3i32(25,50,47), Vec3i32(22,25,47), Vec3i32(30,51,50), Vec3i32(25,30,50), Vec3i32(26,52,51), Vec3i32(30,26,51), Vec3i32(27,53,52), Vec3i32(26,27,52), Vec3i32(6,54,53), Vec3i32(27,6,53), Vec3i32(32,57,54), Vec3i32(6,32,54), Vec3i32(31,58,57), Vec3i32(32,31,57), Vec3i32(29,61,58), Vec3i32(31,29,58), Vec3i32(28,62,61), Vec3i32(29,28,61), Vec3i32(59,62,28), Vec3i32(24,59,28), Vec3i32(60,59,24), Vec3i32(23,60,24), Vec3i32(55,60,23), Vec3i32(19,55,23), Vec3i32(55,19,56), Vec3i32(56,19,20), Vec3i32(56,20,48), Vec3i32(48,20,18), Vec3i32(48,18,49), Vec3i32(49,18,17), Vec3i32(49,17,42), Vec3i32(42,17,15), Vec3i32(42,15,38), Vec3i32(38,15,16), Vec3i32(38,16,63), Vec3i32(63,16,14), Vec3i32(63,14,64), Vec3i32(64,14,13), Vec3i32(64,13,65), Vec3i32(65,13,12), Vec3i32(65,12,66), Vec3i32(66,12,11), Vec3i32(66,11,67), Vec3i32(67,11,10), Vec3i32(67,10,39), Vec3i32(39,10,9) }; break; case TestMesh::ipadstand: - vertices = std::vector{ - Vec3d(17.4344673156738,-2.69879599481136e-16,9.5), Vec3d(14.2814798355103,10,9.5), Vec3d(0,0,9.5), Vec3d(31.7159481048584,10,9.5), Vec3d(62.2344741821289,2.06667568800577e-16,20), Vec3d(31.7159481048584,10,20), Vec3d(17.4344673156738,-2.69879599481136e-16,20), Vec3d(62.2344741821289,10,20), Vec3d(98.2079696655273,10,0), Vec3d(98.2079696655273,8.56525380796383e-16,10), Vec3d(98.2079696655273,0,0), Vec3d(98.2079696655273,10,20), Vec3d(98.2079696655273,0,20), Vec3d(81.6609649658203,-4.39753856997999e-16,10), Vec3d(90.0549850463867,10,10), Vec3d(78.5079803466797,10,10), Vec3d(93.2079696655273,8.56525380796383e-16,10), Vec3d(14.2814798355103,10,20), Vec3d(0,0,20), Vec3d(87.4344711303711,2.81343962782118e-15,20), Vec3d(84.2814788818359,10,20), Vec3d(0,10,20), Vec3d(0,0,0), Vec3d(0,10,0), Vec3d(62.2344741821289,2.06667568800577e-16,30), Vec3d(66.9609756469727,10,30), Vec3d(62.2344741821289,10,30), Vec3d(70.1139602661133,8.5525763717214e-16,30), Vec3d(67.7053375244141,10,28.7107200622559), Vec3d(71.6787109375,1.24046736339707e-15,27.2897701263428) + vertices = std::vector{ + Vec3f(17.4344673156738,-2.69879599481136e-16,9.5), Vec3f(14.2814798355103,10,9.5), Vec3f(0,0,9.5), Vec3f(31.7159481048584,10,9.5), Vec3f(62.2344741821289,2.06667568800577e-16,20), Vec3f(31.7159481048584,10,20), Vec3f(17.4344673156738,-2.69879599481136e-16,20), Vec3f(62.2344741821289,10,20), Vec3f(98.2079696655273,10,0), Vec3f(98.2079696655273,8.56525380796383e-16,10), Vec3f(98.2079696655273,0,0), Vec3f(98.2079696655273,10,20), Vec3f(98.2079696655273,0,20), Vec3f(81.6609649658203,-4.39753856997999e-16,10), Vec3f(90.0549850463867,10,10), Vec3f(78.5079803466797,10,10), Vec3f(93.2079696655273,8.56525380796383e-16,10), Vec3f(14.2814798355103,10,20), Vec3f(0,0,20), Vec3f(87.4344711303711,2.81343962782118e-15,20), Vec3f(84.2814788818359,10,20), Vec3f(0,10,20), Vec3f(0,0,0), Vec3f(0,10,0), Vec3f(62.2344741821289,2.06667568800577e-16,30), Vec3f(66.9609756469727,10,30), Vec3f(62.2344741821289,10,30), Vec3f(70.1139602661133,8.5525763717214e-16,30), Vec3f(67.7053375244141,10,28.7107200622559), Vec3f(71.6787109375,1.24046736339707e-15,27.2897701263428) }; facets = std::vector{ Vec3i32(0,1,2), Vec3i32(1,0,3), Vec3i32(4,5,6), Vec3i32(5,4,7), Vec3i32(8,9,10), Vec3i32(9,11,12), Vec3i32(11,9,8), Vec3i32(13,14,15), Vec3i32(14,13,16), Vec3i32(17,2,1), Vec3i32(2,17,18), Vec3i32(19,11,20), Vec3i32(11,19,12), Vec3i32(17,21,18), Vec3i32(21,2,18), Vec3i32(2,21,22), Vec3i32(22,21,23), Vec3i32(8,22,23), Vec3i32(22,8,10), Vec3i32(24,25,26), Vec3i32(25,24,27), Vec3i32(23,1,8), Vec3i32(1,23,21), Vec3i32(1,21,17), Vec3i32(5,15,3), Vec3i32(15,5,7), Vec3i32(15,7,28), Vec3i32(28,7,26), Vec3i32(28,26,25), Vec3i32(8,14,11), Vec3i32(14,8,3), Vec3i32(3,8,1), Vec3i32(14,3,15), Vec3i32(11,14,20), Vec3i32(26,4,24), Vec3i32(4,26,7), Vec3i32(12,16,9), Vec3i32(16,12,19), Vec3i32(29,4,13), Vec3i32(4,29,24), Vec3i32(24,29,27), Vec3i32(9,22,10), Vec3i32(22,9,0), Vec3i32(0,9,16), Vec3i32(0,16,13), Vec3i32(0,13,6), Vec3i32(6,13,4), Vec3i32(2,22,0), Vec3i32(19,14,16), Vec3i32(14,19,20), Vec3i32(15,29,13), Vec3i32(29,25,27), Vec3i32(25,29,15), Vec3i32(25,15,28), Vec3i32(6,3,0), Vec3i32(3,6,5) }; break; case TestMesh::A: - vertices = std::vector{ - Vec3d(513.075988769531,51.6074333190918,36.0009002685547), Vec3d(516.648803710938,51.7324333190918,36.0009002685547), Vec3d(513.495178222656,51.7324333190918,36.0009002685547), Vec3d(489.391204833984,51.4824333190918,24.0011005401611), Vec3d(488.928588867188,51.7324333190918,24.0011005401611), Vec3d(492.06201171875,51.7324333190918,24.0011005401611), Vec3d(496.840393066406,51.2324333190918,24.0011005401611), Vec3d(495.195404052734,51.7324333190918,24.0011005401611), Vec3d(498.981994628906,51.7324333190918,24.0011005401611), Vec3d(506.966613769531,51.6074333190918,24.0011005401611), Vec3d(510.342010498047,51.7324333190918,24.0011005401611), Vec3d(507.163818359375,51.6074333190918,24.0011005401611), Vec3d(512.515380859375,54.7190322875977,36.0009002685547), Vec3d(514.161987304688,54.5058326721191,36.0009002685547), Vec3d(493.06201171875,54.7190322875977,36.0009002685547), Vec3d(495.195404052734,51.7324333190918,36.0009002685547), Vec3d(496.195404052734,54.7190322875977,36.0009002685547), Vec3d(497.195404052734,57.7058334350586,36.0009002685547), Vec3d(500.851989746094,60.2658309936523,36.0009002685547), Vec3d(498.915405273438,62.8258323669434,36.0009002685547), Vec3d(506.701995849609,62.8258323669434,36.0009002685547), Vec3d(503.648590087891,60.2658309936523,36.0009002685547), Vec3d(508.381805419922,57.7058334350586,36.0009002685547), Vec3d(496.418792724609,60.052433013916,36.0009002685547), Vec3d(506.515197753906,72.2124328613281,36.0009002685547), Vec3d(502.808807373047,74.5324325561523,36.0009002685547), Vec3d(503.781982421875,71.6058349609375,36.0009002685547), Vec3d(515.358764648438,55.4658317565918,36.0009002685547), Vec3d(499.375183105469,76.9058380126953,36.0009002685547), Vec3d(501.168792724609,78.0658340454102,36.0009002685547), Vec3d(504.568786621094,78.0658340454102,36.0009002685547), Vec3d(506.32861328125,81.599235534668,36.0009002685547), Vec3d(502.928588867188,81.599235534668,36.0009002685547), Vec3d(499.528594970703,81.599235534668,36.0009002685547), Vec3d(498.20361328125,77.8658294677734,36.0009002685547), Vec3d(495.195404052734,51.7324333190918,30.0011005401611), Vec3d(498.981994628906,51.7324333190918,27.0011005401611), Vec3d(506.555206298828,51.7324333190918,33.0009002685547), Vec3d(506.555206298828,51.7324333190918,36.0009002685547), Vec3d(510.342010498047,51.7324333190918,36.0009002685547), Vec3d(512.515380859375,54.7190322875977,24.0011005401611), Vec3d(509.361999511719,54.7190322875977,24.0011005401611), Vec3d(508.381805419922,57.7058334350586,24.0011005401611), Vec3d(506.701995849609,62.8258323669434,24.0011005401611), Vec3d(509.188812255859,60.052433013916,24.0011005401611), Vec3d(493.06201171875,54.7190322875977,24.0011005401611), Vec3d(503.648590087891,60.2658309936523,24.0011005401611), Vec3d(500.851989746094,60.2658309936523,24.0011005401611), Vec3d(498.915405273438,62.8258323669434,24.0011005401611), Vec3d(502.808807373047,62.8258323669434,24.0011005401611), Vec3d(491.425201416016,54.5058326721191,24.0011005401611), Vec3d(506.421813964844,76.9058380126953,24.0011005401611), Vec3d(502.808807373047,74.5324325561523,24.0011005401611), Vec3d(504.568786621094,78.0658340454102,24.0011005401611), Vec3d(506.32861328125,81.599235534668,24.0011005401611), Vec3d(507.618804931641,77.8658294677734,24.0011005401611), Vec3d(499.221801757812,72.2124328613281,24.0011005401611), Vec3d(501.835388183594,71.6058349609375,24.0011005401611), Vec3d(501.168792724609,78.0658340454102,24.0011005401611), Vec3d(499.528594970703,81.599235534668,24.0011005401611), Vec3d(502.048583984375,79.8324356079102,24.0011005401611), Vec3d(490.253601074219,55.4658317565918,24.0011005401611), Vec3d(488.928588867188,51.7324333190918,30.0011005401611), Vec3d(488.928588867188,51.7324333190918,36.0009002685547), Vec3d(490.253601074219,55.4658317565918,31.5009002685547), Vec3d(498.20361328125,77.8658294677734,34.5009002685547), Vec3d(508.381805419922,57.7058334350586,30.0011005401611), Vec3d(505.585388183594,57.7058334350586,27.0011005401611), Vec3d(502.788818359375,57.7058334350586,36.0009002685547), Vec3d(499.992004394531,57.7058334350586,33.0009002685547), Vec3d(509.851989746094,53.2258338928223,33.0009002685547), Vec3d(509.361999511719,54.7190322875977,36.0009002685547), Vec3d(508.871795654297,56.2124328613281,27.0011005401611), Vec3d(496.695404052734,56.2124328613281,33.0009002685547), Vec3d(495.695404052734,53.2258338928223,27.0011005401611), Vec3d(506.32861328125,81.599235534668,30.0011005401611), Vec3d(507.618804931641,77.8658294677734,25.5011005401611), Vec3d(515.358764648438,55.4658317565918,34.5009002685547), Vec3d(501.228607177734,81.599235534668,33.0009002685547), Vec3d(504.628601074219,81.599235534668,27.0011005401611), Vec3d(503.781982421875,71.6058349609375,33.0009002685547), Vec3d(502.808807373047,74.5324325561523,30.0011005401611), Vec3d(498.915405273438,62.8258323669434,30.0011005401611), Vec3d(500.861999511719,62.8258323669434,27.0011005401611), Vec3d(502.808807373047,62.8258323669434,36.0009002685547), Vec3d(504.755187988281,62.8258323669434,33.0009002685547), Vec3d(501.835388183594,71.6058349609375,33.0009002685547), Vec3d(499.888793945312,65.7524337768555,33.0009002685547), Vec3d(499.888793945312,65.7524337768555,36.0009002685547), Vec3d(513.128601074219,51.4824333190918,36.0009002685547), Vec3d(513.075988769531,51.6074333190918,24.0011005401611), Vec3d(516.648803710938,51.7324333190918,24.0011005401611), Vec3d(513.128601074219,51.4824333190918,24.0011005401611), Vec3d(513.495178222656,51.7324333190918,24.0011005401611), Vec3d(506.966613769531,51.6074333190918,36.0009002685547), Vec3d(507.163818359375,51.6074333190918,36.0009002685547), Vec3d(490.337799072266,51.4824333190918,24.0011005401611), Vec3d(489.391204833984,51.4824333190918,36.0009002685547), Vec3d(492.06201171875,51.7324333190918,36.0009002685547), Vec3d(490.337799072266,51.4824333190918,36.0009002685547), Vec3d(513.233764648438,51.2324333190918,24.0011005401611), Vec3d(513.233764648438,51.2324333190918,36.0009002685547), Vec3d(504.773803710938,51.4824333190918,36.0009002685547), Vec3d(504.773803710938,51.4824333190918,24.0011005401611), Vec3d(489.266998291016,51.2324333190918,24.0011005401611), Vec3d(489.266998291016,51.2324333190918,36.0009002685547), Vec3d(490.253601074219,55.4658317565918,25.5011005401611), Vec3d(499.528594970703,81.599235534668,30.0011005401611), Vec3d(498.20361328125,77.8658294677734,31.5009002685547), Vec3d(515.358764648438,55.4658317565918,28.5011005401611), Vec3d(515.358764648438,55.4658317565918,25.5011005401611), Vec3d(495.246795654297,61.0124320983887,36.0009002685547), Vec3d(490.253601074219,55.4658317565918,34.5009002685547), Vec3d(490.253601074219,55.4658317565918,36.0009002685547), Vec3d(494.228607177734,66.6658325195312,24.0011005401611), Vec3d(499.068786621094,67.5192337036133,24.0011005401611), Vec3d(498.20361328125,77.8658294677734,25.5011005401611), Vec3d(498.20361328125,77.8658294677734,24.0011005401611), Vec3d(506.608795166016,67.5192337036133,36.0009002685547), Vec3d(509.09521484375,64.7458343505859,36.0009002685547), Vec3d(507.618804931641,77.8658294677734,34.5009002685547), Vec3d(507.618804931641,77.8658294677734,36.0009002685547), Vec3d(510.385406494141,61.0124320983887,24.0011005401611), Vec3d(515.358764648438,55.4658317565918,24.0011005401611), Vec3d(489.32861328125,47.7324333190918,31.5009002685547), Vec3d(492.95361328125,47.7324333190918,33.5634994506836), Vec3d(489.32861328125,47.7324333190918,34.5009002685547), Vec3d(489.32861328125,47.7324333190918,28.5011005401611), Vec3d(489.32861328125,47.7324333190918,25.5011005401611), Vec3d(492.95361328125,47.7324333190918,26.4385013580322), Vec3d(492.95361328125,47.7324333190918,30.5635013580322), Vec3d(492.95361328125,47.7324333190918,32.0634994506836), Vec3d(492.95361328125,47.7324333190918,31.3135013580322), Vec3d(492.95361328125,47.7324333190918,35.4384994506836), Vec3d(489.32861328125,47.7324333190918,36.0009002685547), Vec3d(492.95361328125,47.7324333190918,34.3134994506836), Vec3d(492.95361328125,47.7324333190918,34.6884994506836), Vec3d(492.95361328125,47.7324333190918,27.9385013580322), Vec3d(492.95361328125,47.7324333190918,28.6885013580322), Vec3d(492.95361328125,47.7324333190918,29.0635013580322), Vec3d(489.32861328125,47.7324333190918,24.0011005401611), Vec3d(492.95361328125,47.7324333190918,24.5635013580322), Vec3d(492.95361328125,47.7324333190918,25.6885013580322), Vec3d(492.95361328125,47.7324333190918,25.3135013580322), Vec3d(492.95361328125,47.7324333190918,24.1885013580322), Vec3d(492.95361328125,47.7324333190918,24.0011005401611), Vec3d(513.443786621094,50.7324333190918,24.0011005401611), Vec3d(492.95361328125,47.7324333190918,35.8134994506836), Vec3d(492.95361328125,47.7324333190918,36.0009002685547), Vec3d(513.443786621094,50.7324333190918,36.0009002685547), Vec3d(506.350402832031,51.4824333190918,36.0009002685547), Vec3d(506.350402832031,51.4824333190918,24.0011005401611), Vec3d(492.743804931641,48.2324333190918,24.0011005401611), Vec3d(492.638793945312,48.4824333190918,24.0011005401611), Vec3d(492.743804931641,48.2324333190918,36.0009002685547), Vec3d(492.638793945312,48.4824333190918,36.0009002685547), Vec3d(490.089599609375,50.9824333190918,36.0009002685547), Vec3d(490.089599609375,50.9824333190918,24.0011005401611), Vec3d(510.342010498047,51.7324333190918,30.0011005401611), Vec3d(499.068786621094,67.5192337036133,36.0009002685547), Vec3d(494.228607177734,66.6658325195312,36.0009002685547), Vec3d(499.375183105469,76.9058380126953,24.0011005401611), Vec3d(506.421813964844,76.9058380126953,36.0009002685547), Vec3d(506.608795166016,67.5192337036133,24.0011005401611), Vec3d(505.728607177734,65.7524337768555,24.0011005401611), Vec3d(509.09521484375,64.7458343505859,24.0011005401611), Vec3d(506.701995849609,62.8258323669434,30.0011005401611), Vec3d(505.728607177734,65.7524337768555,27.0011005401611), Vec3d(501.835388183594,71.6058349609375,27.0011005401611), Vec3d(499.888793945312,65.7524337768555,27.0011005401611), Vec3d(494.228607177734,66.6658325195312,30.0011005401611), Vec3d(495.553588867188,70.3992309570312,28.5011005401611), Vec3d(492.903594970703,62.9324340820312,28.5011005401611), Vec3d(495.553588867188,70.3992309570312,31.5009002685547), Vec3d(492.903594970703,62.9324340820312,31.5009002685547), Vec3d(511.488800048828,66.6658325195312,24.0011005401611), Vec3d(511.488800048828,66.6658325195312,30.0011005401611), Vec3d(512.778564453125,62.9324340820312,28.5011005401611), Vec3d(515.358764648438,55.4658317565918,31.5009002685547), Vec3d(507.618804931641,77.8658294677734,31.5009002685547), Vec3d(510.198791503906,70.3992309570312,28.5011005401611), Vec3d(511.488800048828,66.6658325195312,36.0009002685547), Vec3d(512.778564453125,62.9324340820312,31.5009002685547), Vec3d(510.198791503906,70.3992309570312,31.5009002685547), Vec3d(502.788818359375,57.7058334350586,24.0011005401611), Vec3d(497.195404052734,57.7058334350586,30.0011005401611), Vec3d(492.903594970703,62.9324340820312,34.5009002685547), Vec3d(492.903594970703,62.9324340820312,36.0009002685547), Vec3d(495.553588867188,70.3992309570312,24.0011005401611), Vec3d(496.725189208984,69.4392318725586,24.0011005401611), Vec3d(495.553588867188,70.3992309570312,25.5011005401611), Vec3d(495.246795654297,61.0124320983887,24.0011005401611), Vec3d(492.903594970703,62.9324340820312,25.5011005401611), Vec3d(492.903594970703,62.9324340820312,24.0011005401611), Vec3d(495.553588867188,70.3992309570312,36.0009002685547), Vec3d(496.725189208984,69.4392318725586,36.0009002685547), Vec3d(495.553588867188,70.3992309570312,34.5009002685547), Vec3d(510.198791503906,70.3992309570312,36.0009002685547), Vec3d(509.002014160156,69.4392318725586,36.0009002685547), Vec3d(510.198791503906,70.3992309570312,34.5009002685547), Vec3d(512.778564453125,62.9324340820312,25.5011005401611), Vec3d(512.778564453125,62.9324340820312,24.0011005401611), Vec3d(510.198791503906,70.3992309570312,24.0011005401611), Vec3d(509.002014160156,69.4392318725586,24.0011005401611), Vec3d(510.198791503906,70.3992309570312,25.5011005401611), Vec3d(510.385406494141,61.0124320983887,36.0009002685547), Vec3d(512.778564453125,62.9324340820312,34.5009002685547), Vec3d(512.778564453125,62.9324340820312,36.0009002685547), Vec3d(496.840393066406,51.2324333190918,36.0009002685547), Vec3d(498.981994628906,51.7324333190918,36.0009002685547), Vec3d(498.981994628906,51.7324333190918,33.0009002685547), Vec3d(506.555206298828,51.7324333190918,24.0011005401611), Vec3d(506.555206298828,51.7324333190918,27.0011005401611), Vec3d(503.82861328125,47.7324333190918,30.7509002685547), Vec3d(507.45361328125,47.7324333190918,32.8134994506836), Vec3d(503.82861328125,47.7324333190918,33.7509002685547), Vec3d(503.82861328125,47.7324333190918,29.2511005401611), Vec3d(503.82861328125,47.7324333190918,26.2511005401611), Vec3d(507.45361328125,47.7324333190918,27.1885013580322), Vec3d(493.921813964844,57.2792320251465,36.0009002685547), Vec3d(491.425201416016,54.5058326721191,36.0009002685547), Vec3d(497.195404052734,57.7058334350586,24.0011005401611), Vec3d(496.418792724609,60.052433013916,24.0011005401611), Vec3d(509.188812255859,60.052433013916,36.0009002685547), Vec3d(511.675415039062,57.2792320251465,24.0011005401611), Vec3d(514.161987304688,54.5058326721191,24.0011005401611), Vec3d(507.45361328125,47.7324333190918,34.3134994506836), Vec3d(503.82861328125,47.7324333190918,35.2509002685547), Vec3d(507.45361328125,47.7324333190918,25.6885013580322), Vec3d(503.82861328125,47.7324333190918,24.7511005401611), Vec3d(500.20361328125,47.7324333190918,31.6885013580322), Vec3d(500.20361328125,47.7324333190918,28.3135013580322), Vec3d(500.20361328125,47.7324333190918,30.1885013580322), Vec3d(507.45361328125,47.7324333190918,29.8135013580322), Vec3d(507.45361328125,47.7324333190918,31.3135013580322), Vec3d(507.45361328125,47.7324333190918,30.5635013580322), Vec3d(503.82861328125,47.7324333190918,36.0009002685547), Vec3d(507.45361328125,47.7324333190918,35.4384994506836), Vec3d(507.45361328125,47.7324333190918,35.0634994506836), Vec3d(507.45361328125,47.7324333190918,28.6885013580322), Vec3d(507.45361328125,47.7324333190918,29.4385013580322), Vec3d(503.82861328125,47.7324333190918,24.0011005401611), Vec3d(507.45361328125,47.7324333190918,24.5635013580322), Vec3d(507.45361328125,47.7324333190918,24.9385013580322), Vec3d(500.20361328125,47.7324333190918,34.6884994506836), Vec3d(500.20361328125,47.7324333190918,33.1884994506836), Vec3d(500.20361328125,47.7324333190918,33.9384994506836), Vec3d(500.20361328125,47.7324333190918,25.3135013580322), Vec3d(500.20361328125,47.7324333190918,26.8135013580322), Vec3d(500.20361328125,47.7324333190918,26.0635013580322), Vec3d(500.20361328125,47.7324333190918,30.9385013580322), Vec3d(500.20361328125,47.7324333190918,35.0634994506836), Vec3d(500.20361328125,47.7324333190918,35.4384994506836), Vec3d(500.20361328125,47.7324333190918,29.0635013580322), Vec3d(500.20361328125,47.7324333190918,29.4385013580322), Vec3d(500.20361328125,47.7324333190918,24.9385013580322), Vec3d(500.20361328125,47.7324333190918,24.5635013580322), Vec3d(507.45361328125,47.7324333190918,24.1885013580322), Vec3d(507.45361328125,47.7324333190918,24.0011005401611), Vec3d(513.86376953125,49.7324333190918,24.0011005401611), Vec3d(507.45361328125,47.7324333190918,35.8134994506836), Vec3d(507.45361328125,47.7324333190918,36.0009002685547), Vec3d(513.86376953125,49.7324333190918,36.0009002685547), Vec3d(500.20361328125,47.7324333190918,24.1885013580322), Vec3d(500.20361328125,47.7324333190918,24.0011005401611), Vec3d(502.988800048828,49.7324333190918,24.0011005401611), Vec3d(500.20361328125,47.7324333190918,35.8134994506836), Vec3d(500.20361328125,47.7324333190918,36.0009002685547), Vec3d(502.988800048828,49.7324333190918,36.0009002685547), Vec3d(504.755187988281,62.8258323669434,27.0011005401611), Vec3d(499.205383300781,51.2324333190918,36.0009002685547), Vec3d(498.786193847656,51.1074333190918,36.0009002685547), Vec3d(502.358795166016,51.2324333190918,36.0009002685547), Vec3d(499.205383300781,51.2324333190918,24.0011005401611), Vec3d(502.358795166016,51.2324333190918,24.0011005401611), Vec3d(498.786193847656,51.1074333190918,24.0011005401611), Vec3d(502.568786621094,50.7324333190918,24.0011005401611), Vec3d(505.931213378906,51.3574333190918,24.0011005401611), Vec3d(509.503601074219,51.4824333190918,24.0011005401611), Vec3d(502.568786621094,50.7324333190918,36.0009002685547), Vec3d(505.931213378906,51.3574333190918,36.0009002685547), Vec3d(509.503601074219,51.4824333190918,36.0009002685547), Vec3d(499.048583984375,50.4824333190918,36.0009002685547), Vec3d(492.428588867188,48.9824333190918,36.0009002685547), Vec3d(499.048583984375,50.4824333190918,24.0011005401611), Vec3d(492.428588867188,48.9824333190918,24.0011005401611), Vec3d(506.088806152344,50.9824333190918,24.0011005401611), Vec3d(506.036010742188,51.1074333190918,24.0011005401611), Vec3d(506.088806152344,50.9824333190918,36.0009002685547), Vec3d(506.036010742188,51.1074333190918,36.0009002685547), Vec3d(498.891204833984,50.8574333190918,36.0009002685547), Vec3d(498.943786621094,50.7324333190918,36.0009002685547), Vec3d(498.891204833984,50.8574333190918,24.0011005401611), Vec3d(498.943786621094,50.7324333190918,24.0011005401611), Vec3d(499.573608398438,49.2324333190918,24.0011005401611), Vec3d(499.783813476562,48.7324333190918,24.0011005401611), Vec3d(499.573608398438,49.2324333190918,36.0009002685547), Vec3d(499.783813476562,48.7324333190918,36.0009002685547), Vec3d(506.403594970703,50.2324333190918,24.0011005401611), Vec3d(506.298797607422,50.4824333190918,24.0011005401611), Vec3d(506.403594970703,50.2324333190918,36.0009002685547), Vec3d(506.298797607422,50.4824333190918,36.0009002685547), Vec3d(501.228607177734,81.599235534668,27.0011005401611), Vec3d(502.928588867188,81.599235534668,24.0011005401611), Vec3d(499.2587890625,49.9824333190918,36.0009002685547), Vec3d(499.363800048828,49.7324333190918,36.0009002685547), Vec3d(499.2587890625,49.9824333190918,24.0011005401611), Vec3d(499.363800048828,49.7324333190918,24.0011005401611), Vec3d(496.695404052734,56.2124328613281,27.0011005401611), Vec3d(496.195404052734,54.7190322875977,24.0011005401611), Vec3d(509.851989746094,53.2258338928223,27.0011005401611), Vec3d(493.464782714844,51.1074333190918,36.0009002685547), Vec3d(493.464782714844,51.1074333190918,24.0011005401611), Vec3d(502.768798828125,51.7324333190918,24.0011005401611), Vec3d(500.215789794922,51.3574333190918,24.0011005401611), Vec3d(497.628601074219,51.2324333190918,24.0011005401611), Vec3d(502.768798828125,51.7324333190918,36.0009002685547), Vec3d(500.215789794922,51.3574333190918,36.0009002685547), Vec3d(497.628601074219,51.2324333190918,36.0009002685547), Vec3d(507.033813476562,48.7324333190918,24.0011005401611), Vec3d(506.823791503906,49.2324333190918,24.0011005401611), Vec3d(507.033813476562,48.7324333190918,36.0009002685547), Vec3d(506.823791503906,49.2324333190918,36.0009002685547), Vec3d(494.4501953125,51.1074333190918,24.0011005401611), Vec3d(494.4501953125,51.1074333190918,36.0009002685547), Vec3d(500.807006835938,51.3574333190918,36.0009002685547), Vec3d(503.591186523438,51.4824333190918,36.0009002685547), Vec3d(503.591186523438,51.4824333190918,24.0011005401611), Vec3d(500.807006835938,51.3574333190918,24.0011005401611), Vec3d(505.728607177734,65.7524337768555,36.0009002685547), Vec3d(505.728607177734,65.7524337768555,33.0009002685547), Vec3d(499.221801757812,72.2124328613281,36.0009002685547), Vec3d(501.835388183594,71.6058349609375,36.0009002685547), Vec3d(506.515197753906,72.2124328613281,24.0011005401611), Vec3d(503.781982421875,71.6058349609375,24.0011005401611), Vec3d(503.781982421875,71.6058349609375,27.0011005401611), Vec3d(499.888793945312,65.7524337768555,24.0011005401611), Vec3d(495.695404052734,53.2258338928223,33.0009002685547), Vec3d(516.648803710938,51.7324333190918,30.0011005401611), Vec3d(498.20361328125,77.8658294677734,28.5011005401611), Vec3d(505.585388183594,57.7058334350586,33.0009002685547), Vec3d(508.871795654297,56.2124328613281,33.0009002685547), Vec3d(499.992004394531,57.7058334350586,27.0011005401611), Vec3d(504.628601074219,81.599235534668,33.0009002685547), Vec3d(500.861999511719,62.8258323669434,33.0009002685547), Vec3d(496.878601074219,74.1324310302734,27.0011005401611), Vec3d(496.878601074219,74.1324310302734,33.0009002685547), Vec3d(491.57861328125,59.199031829834,27.0011005401611), Vec3d(490.253601074219,55.4658317565918,28.5011005401611), Vec3d(491.57861328125,59.199031829834,33.0009002685547), Vec3d(514.068786621094,59.199031829834,27.0011005401611), Vec3d(514.068786621094,59.199031829834,33.0009002685547), Vec3d(508.908813476562,74.1324310302734,27.0011005401611), Vec3d(507.618804931641,77.8658294677734,28.5011005401611), Vec3d(508.908813476562,74.1324310302734,33.0009002685547), Vec3d(491.271789550781,50.9824333190918,36.0009002685547), Vec3d(490.877807617188,50.9824333190918,36.0009002685547), Vec3d(491.271789550781,50.9824333190918,24.0011005401611), Vec3d(490.877807617188,50.9824333190918,24.0011005401611), Vec3d(495.213806152344,50.9824333190918,36.0009002685547), Vec3d(493.636993408203,50.9824333190918,36.0009002685547), Vec3d(495.213806152344,50.9824333190918,24.0011005401611), Vec3d(493.636993408203,50.9824333190918,24.0011005401611), Vec3d(503.985412597656,51.4824333190918,36.0009002685547), Vec3d(503.985412597656,51.4824333190918,24.0011005401611), Vec3d(511.675415039062,57.2792320251465,36.0009002685547), Vec3d(493.921813964844,57.2792320251465,24.0011005401611), Vec3d(502.768798828125,51.7324333190918,30.0011005401611), Vec3d(506.555206298828,51.7324333190918,30.0011005401611), Vec3d(498.981994628906,51.7324333190918,30.0011005401611), Vec3d(492.848815917969,50.9824333190918,24.0011005401611), Vec3d(492.848815917969,50.9824333190918,36.0009002685547), Vec3d(500.861999511719,68.6792297363281,36.0009002685547), Vec3d(500.861999511719,68.6792297363281,24.0011005401611), Vec3d(496.878601074219,74.1324310302734,24.0011005401611), Vec3d(496.878601074219,74.1324310302734,36.0009002685547), Vec3d(504.755187988281,68.6792297363281,24.0011005401611), Vec3d(504.755187988281,68.6792297363281,36.0009002685547), Vec3d(508.908813476562,74.1324310302734,36.0009002685547), Vec3d(508.908813476562,74.1324310302734,24.0011005401611), Vec3d(505.728607177734,65.7524337768555,30.0011005401611), Vec3d(504.755187988281,68.6792297363281,30.0011005401611), Vec3d(503.781982421875,71.6058349609375,30.0011005401611), Vec3d(500.861999511719,68.6792297363281,30.0011005401611), Vec3d(499.888793945312,65.7524337768555,30.0011005401611), Vec3d(501.835388183594,71.6058349609375,30.0011005401611), Vec3d(491.57861328125,59.199031829834,24.0011005401611), Vec3d(491.57861328125,59.199031829834,36.0009002685547), Vec3d(514.068786621094,59.199031829834,36.0009002685547), Vec3d(514.068786621094,59.199031829834,24.0011005401611), Vec3d(511.07861328125,47.7324333190918,34.8759002685547), Vec3d(511.07861328125,47.7324333190918,31.8759002685547), Vec3d(514.70361328125,47.7324333190918,33.9384994506836), Vec3d(511.07861328125,47.7324333190918,25.1261005401611), Vec3d(514.70361328125,47.7324333190918,26.0635013580322), Vec3d(511.07861328125,47.7324333190918,28.1261005401611), Vec3d(502.788818359375,57.7058334350586,30.0011005401611), Vec3d(502.048583984375,79.8324356079102,36.0009002685547), Vec3d(514.70361328125,47.7324333190918,30.9385013580322), Vec3d(511.07861328125,47.7324333190918,30.3759002685547), Vec3d(514.70361328125,47.7324333190918,29.0635013580322), Vec3d(511.07861328125,47.7324333190918,29.6261005401611), Vec3d(496.57861328125,47.7324333190918,31.1259002685547), Vec3d(496.57861328125,47.7324333190918,32.6259002685547), Vec3d(496.57861328125,47.7324333190918,34.1259002685547), Vec3d(496.57861328125,47.7324333190918,28.8761005401611), Vec3d(496.57861328125,47.7324333190918,27.3761005401611), Vec3d(496.57861328125,47.7324333190918,25.8761005401611), Vec3d(496.57861328125,47.7324333190918,29.6261005401611), Vec3d(514.70361328125,47.7324333190918,35.4384994506836), Vec3d(511.07861328125,47.7324333190918,35.6259002685547), Vec3d(514.70361328125,47.7324333190918,24.5635013580322), Vec3d(511.07861328125,47.7324333190918,24.3761005401611), Vec3d(496.57861328125,47.7324333190918,34.8759002685547), Vec3d(496.57861328125,47.7324333190918,25.1261005401611), Vec3d(496.57861328125,47.7324333190918,35.6259002685547), Vec3d(496.57861328125,47.7324333190918,24.3761005401611), Vec3d(511.07861328125,47.7324333190918,36.0009002685547), Vec3d(511.07861328125,47.7324333190918,24.0011005401611), Vec3d(514.70361328125,47.7324333190918,30.1885013580322), Vec3d(514.70361328125,47.7324333190918,35.8134994506836), Vec3d(514.70361328125,47.7324333190918,29.8135013580322), Vec3d(514.70361328125,47.7324333190918,24.1885013580322), Vec3d(496.57861328125,47.7324333190918,36.0009002685547), Vec3d(496.57861328125,47.7324333190918,24.0011005401611), Vec3d(510.238800048828,49.7324333190918,24.0011005401611), Vec3d(510.238800048828,49.7324333190918,36.0009002685547), Vec3d(514.70361328125,47.7324333190918,24.0011005401611), Vec3d(514.70361328125,47.7324333190918,36.0009002685547), Vec3d(496.158813476562,48.7324333190918,36.0009002685547), Vec3d(496.158813476562,48.7324333190918,24.0011005401611), Vec3d(502.808807373047,62.8258323669434,30.0011005401611), Vec3d(509.608795166016,51.2324333190918,24.0011005401611), Vec3d(509.608795166016,51.2324333190918,36.0009002685547), Vec3d(491.641204833984,50.8574333190918,24.0011005401611), Vec3d(495.423797607422,50.4824333190918,36.0009002685547), Vec3d(495.423797607422,50.4824333190918,24.0011005401611), Vec3d(491.641204833984,50.8574333190918,36.0009002685547), Vec3d(495.528594970703,50.2324333190918,24.0011005401611), Vec3d(492.0087890625,49.9824333190918,24.0011005401611), Vec3d(509.818786621094,50.7324333190918,24.0011005401611), Vec3d(495.948608398438,49.2324333190918,36.0009002685547), Vec3d(495.528594970703,50.2324333190918,36.0009002685547), Vec3d(495.948608398438,49.2324333190918,24.0011005401611), Vec3d(509.818786621094,50.7324333190918,36.0009002685547), Vec3d(492.0087890625,49.9824333190918,36.0009002685547), Vec3d(491.956207275391,50.1074333190918,24.0011005401611), Vec3d(491.956207275391,50.1074333190918,36.0009002685547), Vec3d(502.928588867188,81.599235534668,30.0011005401611), Vec3d(491.851013183594,50.3574333190918,36.0009002685547), Vec3d(491.851013183594,50.3574333190918,24.0011005401611), Vec3d(496.195404052734,54.7190322875977,30.0011005401611), Vec3d(509.361999511719,54.7190322875977,30.0011005401611), Vec3d(488.632598876953,51.7256317138672,30.0011005401611), Vec3d(488.632598876953,51.7256317138672,29.5091018676758), Vec3d(488.632598876953,51.7188339233398,24.0011005401611), Vec3d(488.632598876953,51.7256317138672,27.4929008483887), Vec3d(488.632598876953,51.7324333190918,30.0011005401611), Vec3d(488.632598876953,51.7324333190918,29.0175018310547), Vec3d(488.632598876953,51.7324333190918,24.9847011566162), Vec3d(488.632598876953,51.7324333190918,24.0011005401611), Vec3d(488.632598876953,51.7188339233398,30.0011005401611), Vec3d(488.632598876953,51.7176322937012,24.0011005401611), Vec3d(488.632598876953,51.7182312011719,30.0011005401611), Vec3d(488.632598876953,51.7176322937012,30.0011005401611), Vec3d(488.632598876953,51.715030670166,24.0011005401611), Vec3d(488.632598876953,51.7162322998047,30.0011005401611), Vec3d(488.632598876953,50.761833190918,24.0011005401611), Vec3d(488.632598876953,50.7578315734863,24.0011005401611), Vec3d(488.632598876953,50.7598342895508,30.0011005401611), Vec3d(488.632598876953,50.7522315979004,24.0011005401611), Vec3d(488.632598876953,49.7838325500488,24.0011005401611), Vec3d(488.632598876953,50.2680320739746,30.0011005401611), Vec3d(488.632598876953,51.7046318054199,24.0011005401611), Vec3d(488.632598876953,51.709831237793,30.0011005401611), Vec3d(488.632598876953,50.9120330810547,24.0011005401611), Vec3d(488.632598876953,50.8882331848145,24.0011005401611), Vec3d(488.632598876953,50.9002304077148,30.0011005401611), Vec3d(488.632598876953,47.7324333190918,24.0370998382568), Vec3d(488.632598876953,48.5612335205078,30.0011005401611), Vec3d(488.632598876953,47.7324333190918,24.0011005401611), Vec3d(488.632598876953,47.7324333190918,24.1091003417969), Vec3d(488.632598876953,48.5612335205078,30.0189018249512), Vec3d(488.632598876953,47.7324333190918,25.3211002349854), Vec3d(488.632598876953,48.5612335205078,30.0551013946533), Vec3d(488.632598876953,47.7324333190918,25.4651012420654), Vec3d(488.632598876953,48.5612335205078,30.6609001159668), Vec3d(488.632598876953,47.7324333190918,25.5371017456055), Vec3d(488.632598876953,48.5612335205078,30.7329006195068), Vec3d(488.632598876953,47.7324333190918,25.6091003417969), Vec3d(488.632598876953,48.5612335205078,30.7689018249512), Vec3d(488.632598876953,47.7324333190918,25.8971004486084), Vec3d(488.632598876953,48.5612335205078,30.8051013946533), Vec3d(488.632598876953,47.7324333190918,28.321102142334), Vec3d(488.632598876953,48.5612335205078,30.9491004943848), Vec3d(488.632598876953,47.7324333190918,28.4651012420654), Vec3d(488.632598876953,48.5612335205078,32.1609001159668), Vec3d(488.632598876953,47.7324333190918,28.5371017456055), Vec3d(488.632598876953,48.5612335205078,32.2329025268555), Vec3d(488.632598876953,47.7324333190918,28.6811008453369), Vec3d(488.632598876953,48.5612335205078,32.2689018249512), Vec3d(488.632598876953,47.7324333190918,31.1049003601074), Vec3d(488.632598876953,48.5612335205078,32.3411026000977), Vec3d(488.632598876953,47.7324333190918,31.3929004669189), Vec3d(488.632598876953,49.3900299072266,36.0009002685547), Vec3d(488.632598876953,47.7324333190918,31.536901473999), Vec3d(488.632598876953,47.7324333190918,31.6809005737305), Vec3d(488.632598876953,47.7324333190918,34.1049003601074), Vec3d(488.632598876953,47.7324333190918,34.3929023742676), Vec3d(488.632598876953,47.7324333190918,34.464900970459), Vec3d(488.632598876953,47.7324333190918,34.5369033813477), Vec3d(488.632598876953,47.7324333190918,34.6809005737305), Vec3d(488.632598876953,47.7324333190918,35.8929023742676), Vec3d(488.632598876953,47.7324333190918,35.964900970459), Vec3d(488.632598876953,47.7324333190918,36.0009002685547), Vec3d(488.632598876953,50.8816299438477,24.0011005401611), Vec3d(488.632598876953,50.8850326538086,30.0011005401611), Vec3d(488.632598876953,49.7480316162109,24.0011005401611), Vec3d(488.632598876953,49.7426300048828,24.0011005401611), Vec3d(488.632598876953,49.745231628418,30.0011005401611), Vec3d(488.632598876953,49.7592315673828,24.0011005401611), Vec3d(488.632598876953,49.7536315917969,30.0011005401611), Vec3d(488.632598876953,49.3900299072266,24.0011005401611), Vec3d(488.632598876953,49.5664329528809,30.0011005401611), Vec3d(488.632598876953,50.8786315917969,24.0011005401611), Vec3d(488.632598876953,50.7764320373535,24.0011005401611), Vec3d(488.632598876953,50.8274307250977,30.0011005401611), Vec3d(488.632598876953,50.7550315856934,30.0011005401611), Vec3d(488.632598876953,50.7692337036133,30.0011005401611), Vec3d(488.632598876953,50.9284324645996,24.0011005401611), Vec3d(488.632598876953,50.9202308654785,30.0011005401611), Vec3d(488.632598876953,51.1788330078125,24.0011005401611), Vec3d(488.632598876953,51.139232635498,24.0011005401611), Vec3d(488.632598876953,51.1590309143066,30.0011005401611), Vec3d(488.632598876953,51.2324333190918,24.0011005401611), Vec3d(488.632598876953,51.2056312561035,30.0011005401611), Vec3d(488.632598876953,51.4340324401855,24.0011005401611), Vec3d(488.632598876953,51.3946304321289,24.0011005401611), Vec3d(488.632598876953,51.4142303466797,30.0011005401611), Vec3d(488.632598876953,51.4498329162598,24.0011005401611), Vec3d(488.632598876953,51.5772323608398,30.0011005401611), Vec3d(488.632598876953,51.4418334960938,30.0011005401611), Vec3d(488.632598876953,51.3136329650879,30.0011005401611), Vec3d(488.632598876953,49.7714309692383,30.0011005401611), Vec3d(488.632598876953,51.0338325500488,30.0011005401611), Vec3d(488.632598876953,50.8816299438477,30.0011005401611), Vec3d(488.632598876953,50.8800315856934,30.0011005401611), Vec3d(488.632598876953,51.7188339233398,36.0009002685547), Vec3d(488.632598876953,51.7176322937012,36.0009002685547), Vec3d(488.632598876953,49.3900299072266,30.0011005401611), Vec3d(488.632598876953,50.7522315979004,30.0011005401611), Vec3d(488.632598876953,50.7522315979004,36.0009002685547), Vec3d(488.632598876953,49.7426300048828,30.0011005401611), Vec3d(488.632598876953,49.7426300048828,36.0009002685547), Vec3d(488.632598876953,49.7480316162109,30.0011005401611), Vec3d(488.632598876953,49.7480316162109,36.0009002685547), Vec3d(488.632598876953,51.715030670166,30.0011005401611), Vec3d(488.632598876953,51.715030670166,36.0009002685547), Vec3d(488.632598876953,50.7578315734863,30.0011005401611), Vec3d(488.632598876953,50.7578315734863,36.0009002685547), Vec3d(488.632598876953,50.761833190918,30.0011005401611), Vec3d(488.632598876953,50.761833190918,36.0009002685547), Vec3d(488.632598876953,50.8882331848145,30.0011005401611), Vec3d(488.632598876953,50.8882331848145,36.0009002685547), Vec3d(488.632598876953,49.7592315673828,30.0011005401611), Vec3d(488.632598876953,49.7592315673828,36.0009002685547), Vec3d(488.632598876953,51.1788330078125,30.0011005401611), Vec3d(488.632598876953,51.1788330078125,36.0009002685547), Vec3d(488.632598876953,50.9120330810547,30.0011005401611), Vec3d(488.632598876953,50.9120330810547,36.0009002685547), Vec3d(488.632598876953,51.4498329162598,30.0011005401611), Vec3d(488.632598876953,51.4498329162598,36.0009002685547), Vec3d(488.632598876953,51.7046318054199,30.0011005401611), Vec3d(488.632598876953,51.7046318054199,36.0009002685547), Vec3d(488.632598876953,51.2324333190918,30.0011005401611), Vec3d(488.632598876953,51.2324333190918,36.0009002685547), Vec3d(488.632598876953,51.3946304321289,30.0011005401611), Vec3d(488.632598876953,51.3946304321289,36.0009002685547), Vec3d(488.632598876953,51.4340324401855,30.0011005401611), Vec3d(488.632598876953,51.4340324401855,36.0009002685547), Vec3d(488.632598876953,49.7838325500488,30.0011005401611), Vec3d(488.632598876953,49.7838325500488,36.0009002685547), Vec3d(488.632598876953,50.7764320373535,30.0011005401611), Vec3d(488.632598876953,50.7764320373535,36.0009002685547), Vec3d(488.632598876953,51.139232635498,30.0011005401611), Vec3d(488.632598876953,51.139232635498,36.0009002685547), Vec3d(488.632598876953,50.9284324645996,30.0011005401611), Vec3d(488.632598876953,50.9284324645996,36.0009002685547), Vec3d(488.632598876953,50.8816299438477,36.0009002685547), Vec3d(488.632598876953,50.8786315917969,30.0011005401611), Vec3d(488.632598876953,50.8786315917969,36.0009002685547), Vec3d(488.632598876953,51.7324333190918,35.0173034667969), Vec3d(488.632598876953,51.7324333190918,36.0009002685547), Vec3d(488.632598876953,51.7324333190918,30.9847011566162), Vec3d(517.188415527344,51.7140884399414,24.0011005401611), Vec3d(517.188415527344,51.7140884399414,36.0009002685547), Vec3d(517.188415527344,50.4475173950195,24.0011005401611), Vec3d(517.188415527344,51.7324333190918,35.3734130859375), Vec3d(517.188415527344,51.7324333190918,36.0009002685547), Vec3d(517.188415527344,51.7324333190918,34.1185760498047), Vec3d(517.188415527344,51.7324333190918,31.88330078125), Vec3d(517.188415527344,51.7324333190918,30.0011005401611), Vec3d(517.188415527344,51.7324333190918,28.1187744140625), Vec3d(517.188415527344,51.7324333190918,25.8834266662598), Vec3d(517.188415527344,51.7324333190918,24.6285915374756), Vec3d(517.188415527344,51.7324333190918,24.0011005401611), Vec3d(517.188415527344,47.7324333190918,24.0600452423096), Vec3d(517.188415527344,47.7324333190918,24.0011005401611), Vec3d(517.188415527344,50.4475173950195,36.0009002685547), Vec3d(517.188415527344,47.7324333190918,24.1779975891113), Vec3d(517.188415527344,47.7324333190918,24.6498031616211), Vec3d(517.188415527344,47.7324333190918,28.7625770568848), Vec3d(517.188415527344,47.7324333190918,29.7061901092529), Vec3d(517.188415527344,47.7324333190918,29.9420928955078), Vec3d(517.188415527344,47.7324333190918,30.0600452423096), Vec3d(517.188415527344,47.7324333190918,30.2959480285645), Vec3d(517.188415527344,47.7324333190918,31.2395629882812), Vec3d(517.188415527344,47.7324333190918,35.3521995544434), Vec3d(517.188415527344,47.7324333190918,35.8240051269531), Vec3d(517.188415527344,47.7324333190918,35.9419555664062), Vec3d(517.188415527344,47.7324333190918,36.0009002685547) + vertices = std::vector{ + Vec3f(513.075988769531,51.6074333190918,36.0009002685547), Vec3f(516.648803710938,51.7324333190918,36.0009002685547), Vec3f(513.495178222656,51.7324333190918,36.0009002685547), Vec3f(489.391204833984,51.4824333190918,24.0011005401611), Vec3f(488.928588867188,51.7324333190918,24.0011005401611), Vec3f(492.06201171875,51.7324333190918,24.0011005401611), Vec3f(496.840393066406,51.2324333190918,24.0011005401611), Vec3f(495.195404052734,51.7324333190918,24.0011005401611), Vec3f(498.981994628906,51.7324333190918,24.0011005401611), Vec3f(506.966613769531,51.6074333190918,24.0011005401611), Vec3f(510.342010498047,51.7324333190918,24.0011005401611), Vec3f(507.163818359375,51.6074333190918,24.0011005401611), Vec3f(512.515380859375,54.7190322875977,36.0009002685547), Vec3f(514.161987304688,54.5058326721191,36.0009002685547), Vec3f(493.06201171875,54.7190322875977,36.0009002685547), Vec3f(495.195404052734,51.7324333190918,36.0009002685547), Vec3f(496.195404052734,54.7190322875977,36.0009002685547), Vec3f(497.195404052734,57.7058334350586,36.0009002685547), Vec3f(500.851989746094,60.2658309936523,36.0009002685547), Vec3f(498.915405273438,62.8258323669434,36.0009002685547), Vec3f(506.701995849609,62.8258323669434,36.0009002685547), Vec3f(503.648590087891,60.2658309936523,36.0009002685547), Vec3f(508.381805419922,57.7058334350586,36.0009002685547), Vec3f(496.418792724609,60.052433013916,36.0009002685547), Vec3f(506.515197753906,72.2124328613281,36.0009002685547), Vec3f(502.808807373047,74.5324325561523,36.0009002685547), Vec3f(503.781982421875,71.6058349609375,36.0009002685547), Vec3f(515.358764648438,55.4658317565918,36.0009002685547), Vec3f(499.375183105469,76.9058380126953,36.0009002685547), Vec3f(501.168792724609,78.0658340454102,36.0009002685547), Vec3f(504.568786621094,78.0658340454102,36.0009002685547), Vec3f(506.32861328125,81.599235534668,36.0009002685547), Vec3f(502.928588867188,81.599235534668,36.0009002685547), Vec3f(499.528594970703,81.599235534668,36.0009002685547), Vec3f(498.20361328125,77.8658294677734,36.0009002685547), Vec3f(495.195404052734,51.7324333190918,30.0011005401611), Vec3f(498.981994628906,51.7324333190918,27.0011005401611), Vec3f(506.555206298828,51.7324333190918,33.0009002685547), Vec3f(506.555206298828,51.7324333190918,36.0009002685547), Vec3f(510.342010498047,51.7324333190918,36.0009002685547), Vec3f(512.515380859375,54.7190322875977,24.0011005401611), Vec3f(509.361999511719,54.7190322875977,24.0011005401611), Vec3f(508.381805419922,57.7058334350586,24.0011005401611), Vec3f(506.701995849609,62.8258323669434,24.0011005401611), Vec3f(509.188812255859,60.052433013916,24.0011005401611), Vec3f(493.06201171875,54.7190322875977,24.0011005401611), Vec3f(503.648590087891,60.2658309936523,24.0011005401611), Vec3f(500.851989746094,60.2658309936523,24.0011005401611), Vec3f(498.915405273438,62.8258323669434,24.0011005401611), Vec3f(502.808807373047,62.8258323669434,24.0011005401611), Vec3f(491.425201416016,54.5058326721191,24.0011005401611), Vec3f(506.421813964844,76.9058380126953,24.0011005401611), Vec3f(502.808807373047,74.5324325561523,24.0011005401611), Vec3f(504.568786621094,78.0658340454102,24.0011005401611), Vec3f(506.32861328125,81.599235534668,24.0011005401611), Vec3f(507.618804931641,77.8658294677734,24.0011005401611), Vec3f(499.221801757812,72.2124328613281,24.0011005401611), Vec3f(501.835388183594,71.6058349609375,24.0011005401611), Vec3f(501.168792724609,78.0658340454102,24.0011005401611), Vec3f(499.528594970703,81.599235534668,24.0011005401611), Vec3f(502.048583984375,79.8324356079102,24.0011005401611), Vec3f(490.253601074219,55.4658317565918,24.0011005401611), Vec3f(488.928588867188,51.7324333190918,30.0011005401611), Vec3f(488.928588867188,51.7324333190918,36.0009002685547), Vec3f(490.253601074219,55.4658317565918,31.5009002685547), Vec3f(498.20361328125,77.8658294677734,34.5009002685547), Vec3f(508.381805419922,57.7058334350586,30.0011005401611), Vec3f(505.585388183594,57.7058334350586,27.0011005401611), Vec3f(502.788818359375,57.7058334350586,36.0009002685547), Vec3f(499.992004394531,57.7058334350586,33.0009002685547), Vec3f(509.851989746094,53.2258338928223,33.0009002685547), Vec3f(509.361999511719,54.7190322875977,36.0009002685547), Vec3f(508.871795654297,56.2124328613281,27.0011005401611), Vec3f(496.695404052734,56.2124328613281,33.0009002685547), Vec3f(495.695404052734,53.2258338928223,27.0011005401611), Vec3f(506.32861328125,81.599235534668,30.0011005401611), Vec3f(507.618804931641,77.8658294677734,25.5011005401611), Vec3f(515.358764648438,55.4658317565918,34.5009002685547), Vec3f(501.228607177734,81.599235534668,33.0009002685547), Vec3f(504.628601074219,81.599235534668,27.0011005401611), Vec3f(503.781982421875,71.6058349609375,33.0009002685547), Vec3f(502.808807373047,74.5324325561523,30.0011005401611), Vec3f(498.915405273438,62.8258323669434,30.0011005401611), Vec3f(500.861999511719,62.8258323669434,27.0011005401611), Vec3f(502.808807373047,62.8258323669434,36.0009002685547), Vec3f(504.755187988281,62.8258323669434,33.0009002685547), Vec3f(501.835388183594,71.6058349609375,33.0009002685547), Vec3f(499.888793945312,65.7524337768555,33.0009002685547), Vec3f(499.888793945312,65.7524337768555,36.0009002685547), Vec3f(513.128601074219,51.4824333190918,36.0009002685547), Vec3f(513.075988769531,51.6074333190918,24.0011005401611), Vec3f(516.648803710938,51.7324333190918,24.0011005401611), Vec3f(513.128601074219,51.4824333190918,24.0011005401611), Vec3f(513.495178222656,51.7324333190918,24.0011005401611), Vec3f(506.966613769531,51.6074333190918,36.0009002685547), Vec3f(507.163818359375,51.6074333190918,36.0009002685547), Vec3f(490.337799072266,51.4824333190918,24.0011005401611), Vec3f(489.391204833984,51.4824333190918,36.0009002685547), Vec3f(492.06201171875,51.7324333190918,36.0009002685547), Vec3f(490.337799072266,51.4824333190918,36.0009002685547), Vec3f(513.233764648438,51.2324333190918,24.0011005401611), Vec3f(513.233764648438,51.2324333190918,36.0009002685547), Vec3f(504.773803710938,51.4824333190918,36.0009002685547), Vec3f(504.773803710938,51.4824333190918,24.0011005401611), Vec3f(489.266998291016,51.2324333190918,24.0011005401611), Vec3f(489.266998291016,51.2324333190918,36.0009002685547), Vec3f(490.253601074219,55.4658317565918,25.5011005401611), Vec3f(499.528594970703,81.599235534668,30.0011005401611), Vec3f(498.20361328125,77.8658294677734,31.5009002685547), Vec3f(515.358764648438,55.4658317565918,28.5011005401611), Vec3f(515.358764648438,55.4658317565918,25.5011005401611), Vec3f(495.246795654297,61.0124320983887,36.0009002685547), Vec3f(490.253601074219,55.4658317565918,34.5009002685547), Vec3f(490.253601074219,55.4658317565918,36.0009002685547), Vec3f(494.228607177734,66.6658325195312,24.0011005401611), Vec3f(499.068786621094,67.5192337036133,24.0011005401611), Vec3f(498.20361328125,77.8658294677734,25.5011005401611), Vec3f(498.20361328125,77.8658294677734,24.0011005401611), Vec3f(506.608795166016,67.5192337036133,36.0009002685547), Vec3f(509.09521484375,64.7458343505859,36.0009002685547), Vec3f(507.618804931641,77.8658294677734,34.5009002685547), Vec3f(507.618804931641,77.8658294677734,36.0009002685547), Vec3f(510.385406494141,61.0124320983887,24.0011005401611), Vec3f(515.358764648438,55.4658317565918,24.0011005401611), Vec3f(489.32861328125,47.7324333190918,31.5009002685547), Vec3f(492.95361328125,47.7324333190918,33.5634994506836), Vec3f(489.32861328125,47.7324333190918,34.5009002685547), Vec3f(489.32861328125,47.7324333190918,28.5011005401611), Vec3f(489.32861328125,47.7324333190918,25.5011005401611), Vec3f(492.95361328125,47.7324333190918,26.4385013580322), Vec3f(492.95361328125,47.7324333190918,30.5635013580322), Vec3f(492.95361328125,47.7324333190918,32.0634994506836), Vec3f(492.95361328125,47.7324333190918,31.3135013580322), Vec3f(492.95361328125,47.7324333190918,35.4384994506836), Vec3f(489.32861328125,47.7324333190918,36.0009002685547), Vec3f(492.95361328125,47.7324333190918,34.3134994506836), Vec3f(492.95361328125,47.7324333190918,34.6884994506836), Vec3f(492.95361328125,47.7324333190918,27.9385013580322), Vec3f(492.95361328125,47.7324333190918,28.6885013580322), Vec3f(492.95361328125,47.7324333190918,29.0635013580322), Vec3f(489.32861328125,47.7324333190918,24.0011005401611), Vec3f(492.95361328125,47.7324333190918,24.5635013580322), Vec3f(492.95361328125,47.7324333190918,25.6885013580322), Vec3f(492.95361328125,47.7324333190918,25.3135013580322), Vec3f(492.95361328125,47.7324333190918,24.1885013580322), Vec3f(492.95361328125,47.7324333190918,24.0011005401611), Vec3f(513.443786621094,50.7324333190918,24.0011005401611), Vec3f(492.95361328125,47.7324333190918,35.8134994506836), Vec3f(492.95361328125,47.7324333190918,36.0009002685547), Vec3f(513.443786621094,50.7324333190918,36.0009002685547), Vec3f(506.350402832031,51.4824333190918,36.0009002685547), Vec3f(506.350402832031,51.4824333190918,24.0011005401611), Vec3f(492.743804931641,48.2324333190918,24.0011005401611), Vec3f(492.638793945312,48.4824333190918,24.0011005401611), Vec3f(492.743804931641,48.2324333190918,36.0009002685547), Vec3f(492.638793945312,48.4824333190918,36.0009002685547), Vec3f(490.089599609375,50.9824333190918,36.0009002685547), Vec3f(490.089599609375,50.9824333190918,24.0011005401611), Vec3f(510.342010498047,51.7324333190918,30.0011005401611), Vec3f(499.068786621094,67.5192337036133,36.0009002685547), Vec3f(494.228607177734,66.6658325195312,36.0009002685547), Vec3f(499.375183105469,76.9058380126953,24.0011005401611), Vec3f(506.421813964844,76.9058380126953,36.0009002685547), Vec3f(506.608795166016,67.5192337036133,24.0011005401611), Vec3f(505.728607177734,65.7524337768555,24.0011005401611), Vec3f(509.09521484375,64.7458343505859,24.0011005401611), Vec3f(506.701995849609,62.8258323669434,30.0011005401611), Vec3f(505.728607177734,65.7524337768555,27.0011005401611), Vec3f(501.835388183594,71.6058349609375,27.0011005401611), Vec3f(499.888793945312,65.7524337768555,27.0011005401611), Vec3f(494.228607177734,66.6658325195312,30.0011005401611), Vec3f(495.553588867188,70.3992309570312,28.5011005401611), Vec3f(492.903594970703,62.9324340820312,28.5011005401611), Vec3f(495.553588867188,70.3992309570312,31.5009002685547), Vec3f(492.903594970703,62.9324340820312,31.5009002685547), Vec3f(511.488800048828,66.6658325195312,24.0011005401611), Vec3f(511.488800048828,66.6658325195312,30.0011005401611), Vec3f(512.778564453125,62.9324340820312,28.5011005401611), Vec3f(515.358764648438,55.4658317565918,31.5009002685547), Vec3f(507.618804931641,77.8658294677734,31.5009002685547), Vec3f(510.198791503906,70.3992309570312,28.5011005401611), Vec3f(511.488800048828,66.6658325195312,36.0009002685547), Vec3f(512.778564453125,62.9324340820312,31.5009002685547), Vec3f(510.198791503906,70.3992309570312,31.5009002685547), Vec3f(502.788818359375,57.7058334350586,24.0011005401611), Vec3f(497.195404052734,57.7058334350586,30.0011005401611), Vec3f(492.903594970703,62.9324340820312,34.5009002685547), Vec3f(492.903594970703,62.9324340820312,36.0009002685547), Vec3f(495.553588867188,70.3992309570312,24.0011005401611), Vec3f(496.725189208984,69.4392318725586,24.0011005401611), Vec3f(495.553588867188,70.3992309570312,25.5011005401611), Vec3f(495.246795654297,61.0124320983887,24.0011005401611), Vec3f(492.903594970703,62.9324340820312,25.5011005401611), Vec3f(492.903594970703,62.9324340820312,24.0011005401611), Vec3f(495.553588867188,70.3992309570312,36.0009002685547), Vec3f(496.725189208984,69.4392318725586,36.0009002685547), Vec3f(495.553588867188,70.3992309570312,34.5009002685547), Vec3f(510.198791503906,70.3992309570312,36.0009002685547), Vec3f(509.002014160156,69.4392318725586,36.0009002685547), Vec3f(510.198791503906,70.3992309570312,34.5009002685547), Vec3f(512.778564453125,62.9324340820312,25.5011005401611), Vec3f(512.778564453125,62.9324340820312,24.0011005401611), Vec3f(510.198791503906,70.3992309570312,24.0011005401611), Vec3f(509.002014160156,69.4392318725586,24.0011005401611), Vec3f(510.198791503906,70.3992309570312,25.5011005401611), Vec3f(510.385406494141,61.0124320983887,36.0009002685547), Vec3f(512.778564453125,62.9324340820312,34.5009002685547), Vec3f(512.778564453125,62.9324340820312,36.0009002685547), Vec3f(496.840393066406,51.2324333190918,36.0009002685547), Vec3f(498.981994628906,51.7324333190918,36.0009002685547), Vec3f(498.981994628906,51.7324333190918,33.0009002685547), Vec3f(506.555206298828,51.7324333190918,24.0011005401611), Vec3f(506.555206298828,51.7324333190918,27.0011005401611), Vec3f(503.82861328125,47.7324333190918,30.7509002685547), Vec3f(507.45361328125,47.7324333190918,32.8134994506836), Vec3f(503.82861328125,47.7324333190918,33.7509002685547), Vec3f(503.82861328125,47.7324333190918,29.2511005401611), Vec3f(503.82861328125,47.7324333190918,26.2511005401611), Vec3f(507.45361328125,47.7324333190918,27.1885013580322), Vec3f(493.921813964844,57.2792320251465,36.0009002685547), Vec3f(491.425201416016,54.5058326721191,36.0009002685547), Vec3f(497.195404052734,57.7058334350586,24.0011005401611), Vec3f(496.418792724609,60.052433013916,24.0011005401611), Vec3f(509.188812255859,60.052433013916,36.0009002685547), Vec3f(511.675415039062,57.2792320251465,24.0011005401611), Vec3f(514.161987304688,54.5058326721191,24.0011005401611), Vec3f(507.45361328125,47.7324333190918,34.3134994506836), Vec3f(503.82861328125,47.7324333190918,35.2509002685547), Vec3f(507.45361328125,47.7324333190918,25.6885013580322), Vec3f(503.82861328125,47.7324333190918,24.7511005401611), Vec3f(500.20361328125,47.7324333190918,31.6885013580322), Vec3f(500.20361328125,47.7324333190918,28.3135013580322), Vec3f(500.20361328125,47.7324333190918,30.1885013580322), Vec3f(507.45361328125,47.7324333190918,29.8135013580322), Vec3f(507.45361328125,47.7324333190918,31.3135013580322), Vec3f(507.45361328125,47.7324333190918,30.5635013580322), Vec3f(503.82861328125,47.7324333190918,36.0009002685547), Vec3f(507.45361328125,47.7324333190918,35.4384994506836), Vec3f(507.45361328125,47.7324333190918,35.0634994506836), Vec3f(507.45361328125,47.7324333190918,28.6885013580322), Vec3f(507.45361328125,47.7324333190918,29.4385013580322), Vec3f(503.82861328125,47.7324333190918,24.0011005401611), Vec3f(507.45361328125,47.7324333190918,24.5635013580322), Vec3f(507.45361328125,47.7324333190918,24.9385013580322), Vec3f(500.20361328125,47.7324333190918,34.6884994506836), Vec3f(500.20361328125,47.7324333190918,33.1884994506836), Vec3f(500.20361328125,47.7324333190918,33.9384994506836), Vec3f(500.20361328125,47.7324333190918,25.3135013580322), Vec3f(500.20361328125,47.7324333190918,26.8135013580322), Vec3f(500.20361328125,47.7324333190918,26.0635013580322), Vec3f(500.20361328125,47.7324333190918,30.9385013580322), Vec3f(500.20361328125,47.7324333190918,35.0634994506836), Vec3f(500.20361328125,47.7324333190918,35.4384994506836), Vec3f(500.20361328125,47.7324333190918,29.0635013580322), Vec3f(500.20361328125,47.7324333190918,29.4385013580322), Vec3f(500.20361328125,47.7324333190918,24.9385013580322), Vec3f(500.20361328125,47.7324333190918,24.5635013580322), Vec3f(507.45361328125,47.7324333190918,24.1885013580322), Vec3f(507.45361328125,47.7324333190918,24.0011005401611), Vec3f(513.86376953125,49.7324333190918,24.0011005401611), Vec3f(507.45361328125,47.7324333190918,35.8134994506836), Vec3f(507.45361328125,47.7324333190918,36.0009002685547), Vec3f(513.86376953125,49.7324333190918,36.0009002685547), Vec3f(500.20361328125,47.7324333190918,24.1885013580322), Vec3f(500.20361328125,47.7324333190918,24.0011005401611), Vec3f(502.988800048828,49.7324333190918,24.0011005401611), Vec3f(500.20361328125,47.7324333190918,35.8134994506836), Vec3f(500.20361328125,47.7324333190918,36.0009002685547), Vec3f(502.988800048828,49.7324333190918,36.0009002685547), Vec3f(504.755187988281,62.8258323669434,27.0011005401611), Vec3f(499.205383300781,51.2324333190918,36.0009002685547), Vec3f(498.786193847656,51.1074333190918,36.0009002685547), Vec3f(502.358795166016,51.2324333190918,36.0009002685547), Vec3f(499.205383300781,51.2324333190918,24.0011005401611), Vec3f(502.358795166016,51.2324333190918,24.0011005401611), Vec3f(498.786193847656,51.1074333190918,24.0011005401611), Vec3f(502.568786621094,50.7324333190918,24.0011005401611), Vec3f(505.931213378906,51.3574333190918,24.0011005401611), Vec3f(509.503601074219,51.4824333190918,24.0011005401611), Vec3f(502.568786621094,50.7324333190918,36.0009002685547), Vec3f(505.931213378906,51.3574333190918,36.0009002685547), Vec3f(509.503601074219,51.4824333190918,36.0009002685547), Vec3f(499.048583984375,50.4824333190918,36.0009002685547), Vec3f(492.428588867188,48.9824333190918,36.0009002685547), Vec3f(499.048583984375,50.4824333190918,24.0011005401611), Vec3f(492.428588867188,48.9824333190918,24.0011005401611), Vec3f(506.088806152344,50.9824333190918,24.0011005401611), Vec3f(506.036010742188,51.1074333190918,24.0011005401611), Vec3f(506.088806152344,50.9824333190918,36.0009002685547), Vec3f(506.036010742188,51.1074333190918,36.0009002685547), Vec3f(498.891204833984,50.8574333190918,36.0009002685547), Vec3f(498.943786621094,50.7324333190918,36.0009002685547), Vec3f(498.891204833984,50.8574333190918,24.0011005401611), Vec3f(498.943786621094,50.7324333190918,24.0011005401611), Vec3f(499.573608398438,49.2324333190918,24.0011005401611), Vec3f(499.783813476562,48.7324333190918,24.0011005401611), Vec3f(499.573608398438,49.2324333190918,36.0009002685547), Vec3f(499.783813476562,48.7324333190918,36.0009002685547), Vec3f(506.403594970703,50.2324333190918,24.0011005401611), Vec3f(506.298797607422,50.4824333190918,24.0011005401611), Vec3f(506.403594970703,50.2324333190918,36.0009002685547), Vec3f(506.298797607422,50.4824333190918,36.0009002685547), Vec3f(501.228607177734,81.599235534668,27.0011005401611), Vec3f(502.928588867188,81.599235534668,24.0011005401611), Vec3f(499.2587890625,49.9824333190918,36.0009002685547), Vec3f(499.363800048828,49.7324333190918,36.0009002685547), Vec3f(499.2587890625,49.9824333190918,24.0011005401611), Vec3f(499.363800048828,49.7324333190918,24.0011005401611), Vec3f(496.695404052734,56.2124328613281,27.0011005401611), Vec3f(496.195404052734,54.7190322875977,24.0011005401611), Vec3f(509.851989746094,53.2258338928223,27.0011005401611), Vec3f(493.464782714844,51.1074333190918,36.0009002685547), Vec3f(493.464782714844,51.1074333190918,24.0011005401611), Vec3f(502.768798828125,51.7324333190918,24.0011005401611), Vec3f(500.215789794922,51.3574333190918,24.0011005401611), Vec3f(497.628601074219,51.2324333190918,24.0011005401611), Vec3f(502.768798828125,51.7324333190918,36.0009002685547), Vec3f(500.215789794922,51.3574333190918,36.0009002685547), Vec3f(497.628601074219,51.2324333190918,36.0009002685547), Vec3f(507.033813476562,48.7324333190918,24.0011005401611), Vec3f(506.823791503906,49.2324333190918,24.0011005401611), Vec3f(507.033813476562,48.7324333190918,36.0009002685547), Vec3f(506.823791503906,49.2324333190918,36.0009002685547), Vec3f(494.4501953125,51.1074333190918,24.0011005401611), Vec3f(494.4501953125,51.1074333190918,36.0009002685547), Vec3f(500.807006835938,51.3574333190918,36.0009002685547), Vec3f(503.591186523438,51.4824333190918,36.0009002685547), Vec3f(503.591186523438,51.4824333190918,24.0011005401611), Vec3f(500.807006835938,51.3574333190918,24.0011005401611), Vec3f(505.728607177734,65.7524337768555,36.0009002685547), Vec3f(505.728607177734,65.7524337768555,33.0009002685547), Vec3f(499.221801757812,72.2124328613281,36.0009002685547), Vec3f(501.835388183594,71.6058349609375,36.0009002685547), Vec3f(506.515197753906,72.2124328613281,24.0011005401611), Vec3f(503.781982421875,71.6058349609375,24.0011005401611), Vec3f(503.781982421875,71.6058349609375,27.0011005401611), Vec3f(499.888793945312,65.7524337768555,24.0011005401611), Vec3f(495.695404052734,53.2258338928223,33.0009002685547), Vec3f(516.648803710938,51.7324333190918,30.0011005401611), Vec3f(498.20361328125,77.8658294677734,28.5011005401611), Vec3f(505.585388183594,57.7058334350586,33.0009002685547), Vec3f(508.871795654297,56.2124328613281,33.0009002685547), Vec3f(499.992004394531,57.7058334350586,27.0011005401611), Vec3f(504.628601074219,81.599235534668,33.0009002685547), Vec3f(500.861999511719,62.8258323669434,33.0009002685547), Vec3f(496.878601074219,74.1324310302734,27.0011005401611), Vec3f(496.878601074219,74.1324310302734,33.0009002685547), Vec3f(491.57861328125,59.199031829834,27.0011005401611), Vec3f(490.253601074219,55.4658317565918,28.5011005401611), Vec3f(491.57861328125,59.199031829834,33.0009002685547), Vec3f(514.068786621094,59.199031829834,27.0011005401611), Vec3f(514.068786621094,59.199031829834,33.0009002685547), Vec3f(508.908813476562,74.1324310302734,27.0011005401611), Vec3f(507.618804931641,77.8658294677734,28.5011005401611), Vec3f(508.908813476562,74.1324310302734,33.0009002685547), Vec3f(491.271789550781,50.9824333190918,36.0009002685547), Vec3f(490.877807617188,50.9824333190918,36.0009002685547), Vec3f(491.271789550781,50.9824333190918,24.0011005401611), Vec3f(490.877807617188,50.9824333190918,24.0011005401611), Vec3f(495.213806152344,50.9824333190918,36.0009002685547), Vec3f(493.636993408203,50.9824333190918,36.0009002685547), Vec3f(495.213806152344,50.9824333190918,24.0011005401611), Vec3f(493.636993408203,50.9824333190918,24.0011005401611), Vec3f(503.985412597656,51.4824333190918,36.0009002685547), Vec3f(503.985412597656,51.4824333190918,24.0011005401611), Vec3f(511.675415039062,57.2792320251465,36.0009002685547), Vec3f(493.921813964844,57.2792320251465,24.0011005401611), Vec3f(502.768798828125,51.7324333190918,30.0011005401611), Vec3f(506.555206298828,51.7324333190918,30.0011005401611), Vec3f(498.981994628906,51.7324333190918,30.0011005401611), Vec3f(492.848815917969,50.9824333190918,24.0011005401611), Vec3f(492.848815917969,50.9824333190918,36.0009002685547), Vec3f(500.861999511719,68.6792297363281,36.0009002685547), Vec3f(500.861999511719,68.6792297363281,24.0011005401611), Vec3f(496.878601074219,74.1324310302734,24.0011005401611), Vec3f(496.878601074219,74.1324310302734,36.0009002685547), Vec3f(504.755187988281,68.6792297363281,24.0011005401611), Vec3f(504.755187988281,68.6792297363281,36.0009002685547), Vec3f(508.908813476562,74.1324310302734,36.0009002685547), Vec3f(508.908813476562,74.1324310302734,24.0011005401611), Vec3f(505.728607177734,65.7524337768555,30.0011005401611), Vec3f(504.755187988281,68.6792297363281,30.0011005401611), Vec3f(503.781982421875,71.6058349609375,30.0011005401611), Vec3f(500.861999511719,68.6792297363281,30.0011005401611), Vec3f(499.888793945312,65.7524337768555,30.0011005401611), Vec3f(501.835388183594,71.6058349609375,30.0011005401611), Vec3f(491.57861328125,59.199031829834,24.0011005401611), Vec3f(491.57861328125,59.199031829834,36.0009002685547), Vec3f(514.068786621094,59.199031829834,36.0009002685547), Vec3f(514.068786621094,59.199031829834,24.0011005401611), Vec3f(511.07861328125,47.7324333190918,34.8759002685547), Vec3f(511.07861328125,47.7324333190918,31.8759002685547), Vec3f(514.70361328125,47.7324333190918,33.9384994506836), Vec3f(511.07861328125,47.7324333190918,25.1261005401611), Vec3f(514.70361328125,47.7324333190918,26.0635013580322), Vec3f(511.07861328125,47.7324333190918,28.1261005401611), Vec3f(502.788818359375,57.7058334350586,30.0011005401611), Vec3f(502.048583984375,79.8324356079102,36.0009002685547), Vec3f(514.70361328125,47.7324333190918,30.9385013580322), Vec3f(511.07861328125,47.7324333190918,30.3759002685547), Vec3f(514.70361328125,47.7324333190918,29.0635013580322), Vec3f(511.07861328125,47.7324333190918,29.6261005401611), Vec3f(496.57861328125,47.7324333190918,31.1259002685547), Vec3f(496.57861328125,47.7324333190918,32.6259002685547), Vec3f(496.57861328125,47.7324333190918,34.1259002685547), Vec3f(496.57861328125,47.7324333190918,28.8761005401611), Vec3f(496.57861328125,47.7324333190918,27.3761005401611), Vec3f(496.57861328125,47.7324333190918,25.8761005401611), Vec3f(496.57861328125,47.7324333190918,29.6261005401611), Vec3f(514.70361328125,47.7324333190918,35.4384994506836), Vec3f(511.07861328125,47.7324333190918,35.6259002685547), Vec3f(514.70361328125,47.7324333190918,24.5635013580322), Vec3f(511.07861328125,47.7324333190918,24.3761005401611), Vec3f(496.57861328125,47.7324333190918,34.8759002685547), Vec3f(496.57861328125,47.7324333190918,25.1261005401611), Vec3f(496.57861328125,47.7324333190918,35.6259002685547), Vec3f(496.57861328125,47.7324333190918,24.3761005401611), Vec3f(511.07861328125,47.7324333190918,36.0009002685547), Vec3f(511.07861328125,47.7324333190918,24.0011005401611), Vec3f(514.70361328125,47.7324333190918,30.1885013580322), Vec3f(514.70361328125,47.7324333190918,35.8134994506836), Vec3f(514.70361328125,47.7324333190918,29.8135013580322), Vec3f(514.70361328125,47.7324333190918,24.1885013580322), Vec3f(496.57861328125,47.7324333190918,36.0009002685547), Vec3f(496.57861328125,47.7324333190918,24.0011005401611), Vec3f(510.238800048828,49.7324333190918,24.0011005401611), Vec3f(510.238800048828,49.7324333190918,36.0009002685547), Vec3f(514.70361328125,47.7324333190918,24.0011005401611), Vec3f(514.70361328125,47.7324333190918,36.0009002685547), Vec3f(496.158813476562,48.7324333190918,36.0009002685547), Vec3f(496.158813476562,48.7324333190918,24.0011005401611), Vec3f(502.808807373047,62.8258323669434,30.0011005401611), Vec3f(509.608795166016,51.2324333190918,24.0011005401611), Vec3f(509.608795166016,51.2324333190918,36.0009002685547), Vec3f(491.641204833984,50.8574333190918,24.0011005401611), Vec3f(495.423797607422,50.4824333190918,36.0009002685547), Vec3f(495.423797607422,50.4824333190918,24.0011005401611), Vec3f(491.641204833984,50.8574333190918,36.0009002685547), Vec3f(495.528594970703,50.2324333190918,24.0011005401611), Vec3f(492.0087890625,49.9824333190918,24.0011005401611), Vec3f(509.818786621094,50.7324333190918,24.0011005401611), Vec3f(495.948608398438,49.2324333190918,36.0009002685547), Vec3f(495.528594970703,50.2324333190918,36.0009002685547), Vec3f(495.948608398438,49.2324333190918,24.0011005401611), Vec3f(509.818786621094,50.7324333190918,36.0009002685547), Vec3f(492.0087890625,49.9824333190918,36.0009002685547), Vec3f(491.956207275391,50.1074333190918,24.0011005401611), Vec3f(491.956207275391,50.1074333190918,36.0009002685547), Vec3f(502.928588867188,81.599235534668,30.0011005401611), Vec3f(491.851013183594,50.3574333190918,36.0009002685547), Vec3f(491.851013183594,50.3574333190918,24.0011005401611), Vec3f(496.195404052734,54.7190322875977,30.0011005401611), Vec3f(509.361999511719,54.7190322875977,30.0011005401611), Vec3f(488.632598876953,51.7256317138672,30.0011005401611), Vec3f(488.632598876953,51.7256317138672,29.5091018676758), Vec3f(488.632598876953,51.7188339233398,24.0011005401611), Vec3f(488.632598876953,51.7256317138672,27.4929008483887), Vec3f(488.632598876953,51.7324333190918,30.0011005401611), Vec3f(488.632598876953,51.7324333190918,29.0175018310547), Vec3f(488.632598876953,51.7324333190918,24.9847011566162), Vec3f(488.632598876953,51.7324333190918,24.0011005401611), Vec3f(488.632598876953,51.7188339233398,30.0011005401611), Vec3f(488.632598876953,51.7176322937012,24.0011005401611), Vec3f(488.632598876953,51.7182312011719,30.0011005401611), Vec3f(488.632598876953,51.7176322937012,30.0011005401611), Vec3f(488.632598876953,51.715030670166,24.0011005401611), Vec3f(488.632598876953,51.7162322998047,30.0011005401611), Vec3f(488.632598876953,50.761833190918,24.0011005401611), Vec3f(488.632598876953,50.7578315734863,24.0011005401611), Vec3f(488.632598876953,50.7598342895508,30.0011005401611), Vec3f(488.632598876953,50.7522315979004,24.0011005401611), Vec3f(488.632598876953,49.7838325500488,24.0011005401611), Vec3f(488.632598876953,50.2680320739746,30.0011005401611), Vec3f(488.632598876953,51.7046318054199,24.0011005401611), Vec3f(488.632598876953,51.709831237793,30.0011005401611), Vec3f(488.632598876953,50.9120330810547,24.0011005401611), Vec3f(488.632598876953,50.8882331848145,24.0011005401611), Vec3f(488.632598876953,50.9002304077148,30.0011005401611), Vec3f(488.632598876953,47.7324333190918,24.0370998382568), Vec3f(488.632598876953,48.5612335205078,30.0011005401611), Vec3f(488.632598876953,47.7324333190918,24.0011005401611), Vec3f(488.632598876953,47.7324333190918,24.1091003417969), Vec3f(488.632598876953,48.5612335205078,30.0189018249512), Vec3f(488.632598876953,47.7324333190918,25.3211002349854), Vec3f(488.632598876953,48.5612335205078,30.0551013946533), Vec3f(488.632598876953,47.7324333190918,25.4651012420654), Vec3f(488.632598876953,48.5612335205078,30.6609001159668), Vec3f(488.632598876953,47.7324333190918,25.5371017456055), Vec3f(488.632598876953,48.5612335205078,30.7329006195068), Vec3f(488.632598876953,47.7324333190918,25.6091003417969), Vec3f(488.632598876953,48.5612335205078,30.7689018249512), Vec3f(488.632598876953,47.7324333190918,25.8971004486084), Vec3f(488.632598876953,48.5612335205078,30.8051013946533), Vec3f(488.632598876953,47.7324333190918,28.321102142334), Vec3f(488.632598876953,48.5612335205078,30.9491004943848), Vec3f(488.632598876953,47.7324333190918,28.4651012420654), Vec3f(488.632598876953,48.5612335205078,32.1609001159668), Vec3f(488.632598876953,47.7324333190918,28.5371017456055), Vec3f(488.632598876953,48.5612335205078,32.2329025268555), Vec3f(488.632598876953,47.7324333190918,28.6811008453369), Vec3f(488.632598876953,48.5612335205078,32.2689018249512), Vec3f(488.632598876953,47.7324333190918,31.1049003601074), Vec3f(488.632598876953,48.5612335205078,32.3411026000977), Vec3f(488.632598876953,47.7324333190918,31.3929004669189), Vec3f(488.632598876953,49.3900299072266,36.0009002685547), Vec3f(488.632598876953,47.7324333190918,31.536901473999), Vec3f(488.632598876953,47.7324333190918,31.6809005737305), Vec3f(488.632598876953,47.7324333190918,34.1049003601074), Vec3f(488.632598876953,47.7324333190918,34.3929023742676), Vec3f(488.632598876953,47.7324333190918,34.464900970459), Vec3f(488.632598876953,47.7324333190918,34.5369033813477), Vec3f(488.632598876953,47.7324333190918,34.6809005737305), Vec3f(488.632598876953,47.7324333190918,35.8929023742676), Vec3f(488.632598876953,47.7324333190918,35.964900970459), Vec3f(488.632598876953,47.7324333190918,36.0009002685547), Vec3f(488.632598876953,50.8816299438477,24.0011005401611), Vec3f(488.632598876953,50.8850326538086,30.0011005401611), Vec3f(488.632598876953,49.7480316162109,24.0011005401611), Vec3f(488.632598876953,49.7426300048828,24.0011005401611), Vec3f(488.632598876953,49.745231628418,30.0011005401611), Vec3f(488.632598876953,49.7592315673828,24.0011005401611), Vec3f(488.632598876953,49.7536315917969,30.0011005401611), Vec3f(488.632598876953,49.3900299072266,24.0011005401611), Vec3f(488.632598876953,49.5664329528809,30.0011005401611), Vec3f(488.632598876953,50.8786315917969,24.0011005401611), Vec3f(488.632598876953,50.7764320373535,24.0011005401611), Vec3f(488.632598876953,50.8274307250977,30.0011005401611), Vec3f(488.632598876953,50.7550315856934,30.0011005401611), Vec3f(488.632598876953,50.7692337036133,30.0011005401611), Vec3f(488.632598876953,50.9284324645996,24.0011005401611), Vec3f(488.632598876953,50.9202308654785,30.0011005401611), Vec3f(488.632598876953,51.1788330078125,24.0011005401611), Vec3f(488.632598876953,51.139232635498,24.0011005401611), Vec3f(488.632598876953,51.1590309143066,30.0011005401611), Vec3f(488.632598876953,51.2324333190918,24.0011005401611), Vec3f(488.632598876953,51.2056312561035,30.0011005401611), Vec3f(488.632598876953,51.4340324401855,24.0011005401611), Vec3f(488.632598876953,51.3946304321289,24.0011005401611), Vec3f(488.632598876953,51.4142303466797,30.0011005401611), Vec3f(488.632598876953,51.4498329162598,24.0011005401611), Vec3f(488.632598876953,51.5772323608398,30.0011005401611), Vec3f(488.632598876953,51.4418334960938,30.0011005401611), Vec3f(488.632598876953,51.3136329650879,30.0011005401611), Vec3f(488.632598876953,49.7714309692383,30.0011005401611), Vec3f(488.632598876953,51.0338325500488,30.0011005401611), Vec3f(488.632598876953,50.8816299438477,30.0011005401611), Vec3f(488.632598876953,50.8800315856934,30.0011005401611), Vec3f(488.632598876953,51.7188339233398,36.0009002685547), Vec3f(488.632598876953,51.7176322937012,36.0009002685547), Vec3f(488.632598876953,49.3900299072266,30.0011005401611), Vec3f(488.632598876953,50.7522315979004,30.0011005401611), Vec3f(488.632598876953,50.7522315979004,36.0009002685547), Vec3f(488.632598876953,49.7426300048828,30.0011005401611), Vec3f(488.632598876953,49.7426300048828,36.0009002685547), Vec3f(488.632598876953,49.7480316162109,30.0011005401611), Vec3f(488.632598876953,49.7480316162109,36.0009002685547), Vec3f(488.632598876953,51.715030670166,30.0011005401611), Vec3f(488.632598876953,51.715030670166,36.0009002685547), Vec3f(488.632598876953,50.7578315734863,30.0011005401611), Vec3f(488.632598876953,50.7578315734863,36.0009002685547), Vec3f(488.632598876953,50.761833190918,30.0011005401611), Vec3f(488.632598876953,50.761833190918,36.0009002685547), Vec3f(488.632598876953,50.8882331848145,30.0011005401611), Vec3f(488.632598876953,50.8882331848145,36.0009002685547), Vec3f(488.632598876953,49.7592315673828,30.0011005401611), Vec3f(488.632598876953,49.7592315673828,36.0009002685547), Vec3f(488.632598876953,51.1788330078125,30.0011005401611), Vec3f(488.632598876953,51.1788330078125,36.0009002685547), Vec3f(488.632598876953,50.9120330810547,30.0011005401611), Vec3f(488.632598876953,50.9120330810547,36.0009002685547), Vec3f(488.632598876953,51.4498329162598,30.0011005401611), Vec3f(488.632598876953,51.4498329162598,36.0009002685547), Vec3f(488.632598876953,51.7046318054199,30.0011005401611), Vec3f(488.632598876953,51.7046318054199,36.0009002685547), Vec3f(488.632598876953,51.2324333190918,30.0011005401611), Vec3f(488.632598876953,51.2324333190918,36.0009002685547), Vec3f(488.632598876953,51.3946304321289,30.0011005401611), Vec3f(488.632598876953,51.3946304321289,36.0009002685547), Vec3f(488.632598876953,51.4340324401855,30.0011005401611), Vec3f(488.632598876953,51.4340324401855,36.0009002685547), Vec3f(488.632598876953,49.7838325500488,30.0011005401611), Vec3f(488.632598876953,49.7838325500488,36.0009002685547), Vec3f(488.632598876953,50.7764320373535,30.0011005401611), Vec3f(488.632598876953,50.7764320373535,36.0009002685547), Vec3f(488.632598876953,51.139232635498,30.0011005401611), Vec3f(488.632598876953,51.139232635498,36.0009002685547), Vec3f(488.632598876953,50.9284324645996,30.0011005401611), Vec3f(488.632598876953,50.9284324645996,36.0009002685547), Vec3f(488.632598876953,50.8816299438477,36.0009002685547), Vec3f(488.632598876953,50.8786315917969,30.0011005401611), Vec3f(488.632598876953,50.8786315917969,36.0009002685547), Vec3f(488.632598876953,51.7324333190918,35.0173034667969), Vec3f(488.632598876953,51.7324333190918,36.0009002685547), Vec3f(488.632598876953,51.7324333190918,30.9847011566162), Vec3f(517.188415527344,51.7140884399414,24.0011005401611), Vec3f(517.188415527344,51.7140884399414,36.0009002685547), Vec3f(517.188415527344,50.4475173950195,24.0011005401611), Vec3f(517.188415527344,51.7324333190918,35.3734130859375), Vec3f(517.188415527344,51.7324333190918,36.0009002685547), Vec3f(517.188415527344,51.7324333190918,34.1185760498047), Vec3f(517.188415527344,51.7324333190918,31.88330078125), Vec3f(517.188415527344,51.7324333190918,30.0011005401611), Vec3f(517.188415527344,51.7324333190918,28.1187744140625), Vec3f(517.188415527344,51.7324333190918,25.8834266662598), Vec3f(517.188415527344,51.7324333190918,24.6285915374756), Vec3f(517.188415527344,51.7324333190918,24.0011005401611), Vec3f(517.188415527344,47.7324333190918,24.0600452423096), Vec3f(517.188415527344,47.7324333190918,24.0011005401611), Vec3f(517.188415527344,50.4475173950195,36.0009002685547), Vec3f(517.188415527344,47.7324333190918,24.1779975891113), Vec3f(517.188415527344,47.7324333190918,24.6498031616211), Vec3f(517.188415527344,47.7324333190918,28.7625770568848), Vec3f(517.188415527344,47.7324333190918,29.7061901092529), Vec3f(517.188415527344,47.7324333190918,29.9420928955078), Vec3f(517.188415527344,47.7324333190918,30.0600452423096), Vec3f(517.188415527344,47.7324333190918,30.2959480285645), Vec3f(517.188415527344,47.7324333190918,31.2395629882812), Vec3f(517.188415527344,47.7324333190918,35.3521995544434), Vec3f(517.188415527344,47.7324333190918,35.8240051269531), Vec3f(517.188415527344,47.7324333190918,35.9419555664062), Vec3f(517.188415527344,47.7324333190918,36.0009002685547) }; facets = std::vector{ Vec3i32(0,1,2), Vec3i32(3,4,5), Vec3i32(6,7,8), Vec3i32(9,10,11), Vec3i32(12,2,1), Vec3i32(12,1,13), Vec3i32(14,15,16), Vec3i32(17,18,19), Vec3i32(20,21,22), Vec3i32(17,19,23), Vec3i32(24,25,26), Vec3i32(27,13,1), Vec3i32(28,25,29), Vec3i32(30,31,32), Vec3i32(28,33,34), Vec3i32(35,36,7), Vec3i32(37,38,39), Vec3i32(40,10,41), Vec3i32(42,43,44), Vec3i32(45,5,4), Vec3i32(46,47,48), Vec3i32(46,48,49), Vec3i32(45,4,50), Vec3i32(51,52,53), Vec3i32(51,54,55), Vec3i32(56,52,57), Vec3i32(58,59,60), Vec3i32(61,50,4), Vec3i32(62,63,64), Vec3i32(65,34,33), Vec3i32(66,67,42), Vec3i32(68,17,69), Vec3i32(70,71,22), Vec3i32(66,42,72), Vec3i32(73,16,15), Vec3i32(35,7,74), Vec3i32(75,76,54), Vec3i32(77,27,1), Vec3i32(78,32,31), Vec3i32(75,54,79), Vec3i32(80,26,25), Vec3i32(81,80,25), Vec3i32(82,83,48), Vec3i32(84,20,85), Vec3i32(81,25,86), Vec3i32(87,88,19), Vec3i32(0,89,1), Vec3i32(90,91,92), Vec3i32(90,10,93), Vec3i32(38,94,39), Vec3i32(94,95,39), Vec3i32(3,7,96), Vec3i32(97,15,98), Vec3i32(97,99,15), Vec3i32(92,91,100), Vec3i32(89,101,1), Vec3i32(102,39,95), Vec3i32(103,11,10), Vec3i32(104,96,7), Vec3i32(105,15,99), Vec3i32(106,61,4), Vec3i32(107,108,33), Vec3i32(76,55,54), Vec3i32(109,91,110), Vec3i32(111,23,19), Vec3i32(112,63,113), Vec3i32(114,115,48), Vec3i32(116,59,117), Vec3i32(118,20,119), Vec3i32(120,31,121), Vec3i32(122,44,43), Vec3i32(110,91,123), Vec3i32(124,125,126), Vec3i32(127,128,129), Vec3i32(127,130,124), Vec3i32(131,124,132), Vec3i32(126,133,134), Vec3i32(135,136,126), Vec3i32(137,138,127), Vec3i32(139,127,138), Vec3i32(128,140,141), Vec3i32(142,128,143), Vec3i32(144,140,145), Vec3i32(100,91,146), Vec3i32(147,148,134), Vec3i32(101,149,1), Vec3i32(102,150,39), Vec3i32(103,10,151), Vec3i32(145,140,152), Vec3i32(152,140,153), Vec3i32(148,154,134), Vec3i32(154,155,134), Vec3i32(156,15,105), Vec3i32(157,104,7), Vec3i32(36,8,7), Vec3i32(158,37,39), Vec3i32(159,19,88), Vec3i32(160,19,159), Vec3i32(161,59,58), Vec3i32(161,117,59), Vec3i32(162,31,30), Vec3i32(162,121,31), Vec3i32(163,43,164), Vec3i32(163,165,43), Vec3i32(166,167,43), Vec3i32(167,164,43), Vec3i32(168,57,52), Vec3i32(82,48,169), Vec3i32(114,170,171), Vec3i32(108,65,33), Vec3i32(64,63,112), Vec3i32(114,172,170), Vec3i32(160,173,170), Vec3i32(171,170,173), Vec3i32(172,174,170), Vec3i32(160,170,174), Vec3i32(175,176,177), Vec3i32(178,77,1), Vec3i32(179,31,120), Vec3i32(175,180,176), Vec3i32(181,182,176), Vec3i32(177,176,182), Vec3i32(180,183,176), Vec3i32(181,176,183), Vec3i32(184,42,67), Vec3i32(185,69,17), Vec3i32(160,111,19), Vec3i32(186,187,160), Vec3i32(188,189,114), Vec3i32(190,188,114), Vec3i32(114,48,191), Vec3i32(192,114,193), Vec3i32(194,160,195), Vec3i32(196,160,194), Vec3i32(197,198,181), Vec3i32(199,197,181), Vec3i32(122,43,165), Vec3i32(200,201,175), Vec3i32(202,175,203), Vec3i32(204,175,202), Vec3i32(205,119,20), Vec3i32(206,181,207), Vec3i32(208,209,15), Vec3i32(210,15,209), Vec3i32(211,10,9), Vec3i32(212,10,211), Vec3i32(213,214,215), Vec3i32(216,217,218), Vec3i32(219,14,17), Vec3i32(113,63,220), Vec3i32(221,222,48), Vec3i32(191,48,222), Vec3i32(22,223,20), Vec3i32(205,20,223), Vec3i32(224,40,42), Vec3i32(123,91,225), Vec3i32(214,226,215), Vec3i32(227,215,226), Vec3i32(218,217,228), Vec3i32(229,228,217), Vec3i32(215,230,213), Vec3i32(125,135,126), Vec3i32(217,216,231), Vec3i32(129,128,142), Vec3i32(216,213,232), Vec3i32(130,132,124), Vec3i32(213,216,233), Vec3i32(234,213,235), Vec3i32(236,227,237), Vec3i32(238,237,227), Vec3i32(239,240,216), Vec3i32(233,216,240), Vec3i32(241,242,229), Vec3i32(243,229,242), Vec3i32(215,227,244), Vec3i32(245,215,246), Vec3i32(217,247,229), Vec3i32(248,249,217), Vec3i32(232,213,250), Vec3i32(230,250,213), Vec3i32(133,147,134), Vec3i32(244,227,251), Vec3i32(236,252,227), Vec3i32(251,227,252), Vec3i32(231,216,253), Vec3i32(254,253,216), Vec3i32(141,140,144), Vec3i32(247,255,229), Vec3i32(241,229,256), Vec3i32(255,256,229), Vec3i32(257,241,258), Vec3i32(259,146,91), Vec3i32(260,261,236), Vec3i32(262,1,149), Vec3i32(263,264,241), Vec3i32(265,241,264), Vec3i32(266,236,267), Vec3i32(268,267,236), Vec3i32(49,48,83), Vec3i32(166,43,269), Vec3i32(270,271,272), Vec3i32(273,274,275), Vec3i32(276,274,277), Vec3i32(278,151,10), Vec3i32(279,280,272), Vec3i32(281,39,150), Vec3i32(272,282,279), Vec3i32(155,283,134), Vec3i32(274,276,284), Vec3i32(153,140,285), Vec3i32(286,276,287), Vec3i32(265,276,286), Vec3i32(288,289,279), Vec3i32(268,288,279), Vec3i32(290,291,272), Vec3i32(271,290,272), Vec3i32(292,274,293), Vec3i32(275,274,292), Vec3i32(294,265,295), Vec3i32(276,265,294), Vec3i32(296,297,268), Vec3i32(279,296,268), Vec3i32(241,265,298), Vec3i32(298,265,299), Vec3i32(236,300,268), Vec3i32(300,301,268), Vec3i32(107,33,78), Vec3i32(302,303,59), Vec3i32(304,305,279), Vec3i32(282,304,279), Vec3i32(306,276,307), Vec3i32(284,276,306), Vec3i32(185,17,73), Vec3i32(308,309,221), Vec3i32(158,39,70), Vec3i32(310,41,10), Vec3i32(15,311,208), Vec3i32(7,6,312), Vec3i32(313,314,6), Vec3i32(315,6,314), Vec3i32(316,208,317), Vec3i32(318,317,208), Vec3i32(258,241,319), Vec3i32(319,241,320), Vec3i32(261,321,236), Vec3i32(321,322,236), Vec3i32(6,315,323), Vec3i32(208,324,318), Vec3i32(270,325,318), Vec3i32(326,318,325), Vec3i32(327,328,315), Vec3i32(273,315,328), Vec3i32(118,329,20), Vec3i32(330,20,329), Vec3i32(331,332,25), Vec3i32(86,25,332), Vec3i32(333,334,52), Vec3i32(335,52,334), Vec3i32(115,336,48), Vec3i32(169,48,336), Vec3i32(62,106,4), Vec3i32(35,15,210), Vec3i32(35,337,15), Vec3i32(158,10,212), Vec3i32(158,310,10), Vec3i32(338,178,1), Vec3i32(339,59,116), Vec3i32(107,302,59), Vec3i32(66,22,340), Vec3i32(66,341,22), Vec3i32(185,221,342), Vec3i32(185,308,221), Vec3i32(75,31,179), Vec3i32(75,343,31), Vec3i32(166,20,330), Vec3i32(166,85,20), Vec3i32(81,52,335), Vec3i32(81,168,52), Vec3i32(82,19,344), Vec3i32(82,87,19), Vec3i32(108,339,345), Vec3i32(346,108,345), Vec3i32(64,347,348), Vec3i32(349,347,64), Vec3i32(178,109,350), Vec3i32(351,178,350), Vec3i32(179,352,353), Vec3i32(354,352,179), Vec3i32(355,208,356), Vec3i32(356,208,311), Vec3i32(357,358,6), Vec3i32(358,312,6), Vec3i32(68,22,21), Vec3i32(68,340,22), Vec3i32(221,48,47), Vec3i32(184,342,221), Vec3i32(359,270,360), Vec3i32(318,360,270), Vec3i32(361,362,273), Vec3i32(315,273,362), Vec3i32(272,102,270), Vec3i32(363,270,102), Vec3i32(274,273,103), Vec3i32(364,103,273), Vec3i32(21,19,18), Vec3i32(21,20,84), Vec3i32(184,46,42), Vec3i32(43,42,46), Vec3i32(12,22,71), Vec3i32(365,22,12), Vec3i32(14,98,15), Vec3i32(14,220,63), Vec3i32(40,93,10), Vec3i32(40,225,91), Vec3i32(45,221,309), Vec3i32(366,221,45), Vec3i32(313,367,212), Vec3i32(212,367,368), Vec3i32(36,369,367), Vec3i32(313,36,367), Vec3i32(316,37,367), Vec3i32(37,368,367), Vec3i32(210,367,369), Vec3i32(316,367,210), Vec3i32(362,370,315), Vec3i32(370,323,315), Vec3i32(360,318,371), Vec3i32(371,318,324), Vec3i32(372,331,159), Vec3i32(159,195,160), Vec3i32(373,115,56), Vec3i32(115,114,189), Vec3i32(52,56,161), Vec3i32(374,161,56), Vec3i32(25,28,331), Vec3i32(375,331,28), Vec3i32(376,333,163), Vec3i32(163,203,175), Vec3i32(377,118,24), Vec3i32(118,181,198), Vec3i32(25,24,162), Vec3i32(378,162,24), Vec3i32(52,51,333), Vec3i32(379,333,51), Vec3i32(167,380,381), Vec3i32(376,167,381), Vec3i32(377,381,330), Vec3i32(330,381,380), Vec3i32(335,381,382), Vec3i32(376,381,335), Vec3i32(373,383,169), Vec3i32(169,383,384), Vec3i32(168,385,383), Vec3i32(373,168,383), Vec3i32(372,87,383), Vec3i32(87,384,383), Vec3i32(377,80,381), Vec3i32(80,382,381), Vec3i32(86,383,385), Vec3i32(372,383,86), Vec3i32(106,348,347), Vec3i32(386,106,347), Vec3i32(375,65,346), Vec3i32(108,346,65), Vec3i32(64,112,349), Vec3i32(387,349,112), Vec3i32(171,190,114), Vec3i32(346,345,171), Vec3i32(374,190,345), Vec3i32(171,345,190), Vec3i32(349,172,347), Vec3i32(172,114,192), Vec3i32(386,347,192), Vec3i32(172,192,347), Vec3i32(173,160,196), Vec3i32(171,173,346), Vec3i32(375,346,196), Vec3i32(173,196,346), Vec3i32(172,349,174), Vec3i32(174,186,160), Vec3i32(387,186,349), Vec3i32(174,349,186), Vec3i32(64,348,62), Vec3i32(106,62,348), Vec3i32(108,107,339), Vec3i32(59,339,107), Vec3i32(374,345,116), Vec3i32(339,116,345), Vec3i32(76,353,352), Vec3i32(379,76,352), Vec3i32(388,77,351), Vec3i32(178,351,77), Vec3i32(179,120,354), Vec3i32(378,354,120), Vec3i32(177,200,175), Vec3i32(351,350,177), Vec3i32(389,200,350), Vec3i32(177,350,200), Vec3i32(354,180,352), Vec3i32(180,175,204), Vec3i32(379,352,204), Vec3i32(180,204,352), Vec3i32(182,181,206), Vec3i32(177,182,351), Vec3i32(388,351,206), Vec3i32(182,206,351), Vec3i32(180,354,183), Vec3i32(183,199,181), Vec3i32(378,199,354), Vec3i32(183,354,199), Vec3i32(91,109,338), Vec3i32(178,338,109), Vec3i32(76,75,353), Vec3i32(179,353,75), Vec3i32(389,350,110), Vec3i32(109,110,350), Vec3i32(390,391,392), Vec3i32(393,394,395), Vec3i32(224,122,389), Vec3i32(122,175,201), Vec3i32(365,388,205), Vec3i32(205,207,181), Vec3i32(66,340,396), Vec3i32(68,396,340), Vec3i32(184,396,342), Vec3i32(185,342,396), Vec3i32(66,396,67), Vec3i32(184,67,396), Vec3i32(68,69,396), Vec3i32(185,396,69), Vec3i32(219,111,387), Vec3i32(111,160,187), Vec3i32(366,386,191), Vec3i32(191,193,114), Vec3i32(150,272,280), Vec3i32(102,272,150), Vec3i32(151,277,274), Vec3i32(103,151,274), Vec3i32(161,374,117), Vec3i32(116,117,374), Vec3i32(366,61,386), Vec3i32(106,386,61), Vec3i32(111,187,387), Vec3i32(186,387,187), Vec3i32(56,188,374), Vec3i32(190,374,188), Vec3i32(191,386,193), Vec3i32(192,193,386), Vec3i32(331,375,194), Vec3i32(196,194,375), Vec3i32(28,34,375), Vec3i32(65,375,34), Vec3i32(219,387,113), Vec3i32(112,113,387), Vec3i32(224,389,123), Vec3i32(110,123,389), Vec3i32(51,55,379), Vec3i32(76,379,55), Vec3i32(24,197,378), Vec3i32(199,378,197), Vec3i32(122,201,389), Vec3i32(200,389,201), Vec3i32(333,379,202), Vec3i32(204,202,379), Vec3i32(205,388,207), Vec3i32(206,207,388), Vec3i32(365,27,388), Vec3i32(77,388,27), Vec3i32(162,378,121), Vec3i32(120,121,378), Vec3i32(162,30,25), Vec3i32(30,29,25), Vec3i32(51,53,54), Vec3i32(303,60,59), Vec3i32(28,29,33), Vec3i32(29,397,33), Vec3i32(161,58,52), Vec3i32(53,52,58), Vec3i32(21,84,19), Vec3i32(84,344,19), Vec3i32(46,49,43), Vec3i32(49,269,43), Vec3i32(208,316,209), Vec3i32(210,209,316), Vec3i32(327,313,211), Vec3i32(212,211,313), Vec3i32(36,35,369), Vec3i32(210,369,35), Vec3i32(37,158,368), Vec3i32(212,368,158), Vec3i32(6,8,313), Vec3i32(36,313,8), Vec3i32(326,38,316), Vec3i32(37,316,38), Vec3i32(392,391,398), Vec3i32(399,398,391), Vec3i32(394,400,395), Vec3i32(401,395,400), Vec3i32(390,214,391), Vec3i32(214,213,234), Vec3i32(393,395,218), Vec3i32(218,239,216), Vec3i32(402,230,403), Vec3i32(230,215,245), Vec3i32(125,124,131), Vec3i32(404,125,403), Vec3i32(405,406,231), Vec3i32(231,248,217), Vec3i32(129,137,127), Vec3i32(407,406,129), Vec3i32(130,127,139), Vec3i32(402,130,408), Vec3i32(194,195,331), Vec3i32(159,331,195), Vec3i32(115,189,56), Vec3i32(188,56,189), Vec3i32(14,219,220), Vec3i32(113,220,219), Vec3i32(45,50,366), Vec3i32(61,366,50), Vec3i32(221,366,222), Vec3i32(191,222,366), Vec3i32(17,23,219), Vec3i32(111,219,23), Vec3i32(118,198,24), Vec3i32(197,24,198), Vec3i32(202,203,333), Vec3i32(163,333,203), Vec3i32(40,224,225), Vec3i32(123,225,224), Vec3i32(12,13,365), Vec3i32(27,365,13), Vec3i32(22,365,223), Vec3i32(205,223,365), Vec3i32(42,44,224), Vec3i32(122,224,44), Vec3i32(399,391,234), Vec3i32(214,234,391), Vec3i32(401,239,395), Vec3i32(218,395,239), Vec3i32(214,390,226), Vec3i32(226,238,227), Vec3i32(218,228,393), Vec3i32(228,229,243), Vec3i32(401,399,233), Vec3i32(233,235,213), Vec3i32(392,409,390), Vec3i32(410,390,409), Vec3i32(394,393,411), Vec3i32(412,411,393), Vec3i32(402,403,131), Vec3i32(125,131,403), Vec3i32(405,137,406), Vec3i32(129,406,137), Vec3i32(405,408,139), Vec3i32(130,139,408), Vec3i32(230,245,403), Vec3i32(404,403,245), Vec3i32(231,406,248), Vec3i32(407,248,406), Vec3i32(232,254,216), Vec3i32(402,408,232), Vec3i32(413,404,244), Vec3i32(244,246,215), Vec3i32(414,247,407), Vec3i32(247,217,249), Vec3i32(133,126,136), Vec3i32(415,133,413), Vec3i32(141,143,128), Vec3i32(416,414,141), Vec3i32(410,238,390), Vec3i32(226,390,238), Vec3i32(412,393,243), Vec3i32(228,243,393), Vec3i32(233,399,235), Vec3i32(234,235,399), Vec3i32(237,260,236), Vec3i32(238,410,237), Vec3i32(417,260,410), Vec3i32(237,410,260), Vec3i32(239,401,240), Vec3i32(233,240,401), Vec3i32(242,241,257), Vec3i32(243,242,412), Vec3i32(418,412,257), Vec3i32(242,257,412), Vec3i32(401,419,399), Vec3i32(398,399,419), Vec3i32(417,410,420), Vec3i32(409,420,410), Vec3i32(400,421,401), Vec3i32(419,401,421), Vec3i32(418,422,412), Vec3i32(411,412,422), Vec3i32(413,135,404), Vec3i32(125,404,135), Vec3i32(414,407,142), Vec3i32(129,142,407), Vec3i32(130,402,132), Vec3i32(131,132,402), Vec3i32(133,136,413), Vec3i32(135,413,136), Vec3i32(423,147,415), Vec3i32(133,415,147), Vec3i32(137,405,138), Vec3i32(139,138,405), Vec3i32(141,414,143), Vec3i32(142,143,414), Vec3i32(424,416,144), Vec3i32(141,144,416), Vec3i32(405,254,408), Vec3i32(232,408,254), Vec3i32(244,404,246), Vec3i32(245,246,404), Vec3i32(247,249,407), Vec3i32(248,407,249), Vec3i32(232,250,402), Vec3i32(230,402,250), Vec3i32(415,413,251), Vec3i32(244,251,413), Vec3i32(252,236,266), Vec3i32(251,252,415), Vec3i32(423,415,266), Vec3i32(252,266,415), Vec3i32(231,253,405), Vec3i32(254,405,253), Vec3i32(416,255,414), Vec3i32(247,414,255), Vec3i32(256,263,241), Vec3i32(255,416,256), Vec3i32(424,263,416), Vec3i32(256,416,263), Vec3i32(257,258,418), Vec3i32(425,418,258), Vec3i32(260,417,261), Vec3i32(426,261,417), Vec3i32(422,418,427), Vec3i32(427,259,91), Vec3i32(420,428,417), Vec3i32(428,1,262), Vec3i32(147,423,148), Vec3i32(429,148,423), Vec3i32(263,424,264), Vec3i32(264,295,265), Vec3i32(266,267,423), Vec3i32(267,268,297), Vec3i32(144,145,424), Vec3i32(430,424,145), Vec3i32(49,431,269), Vec3i32(166,269,431), Vec3i32(82,431,83), Vec3i32(49,83,431), Vec3i32(84,85,431), Vec3i32(166,431,85), Vec3i32(82,344,431), Vec3i32(84,431,344), Vec3i32(432,278,90), Vec3i32(10,90,278), Vec3i32(433,0,281), Vec3i32(39,281,0), Vec3i32(362,361,434), Vec3i32(435,271,359), Vec3i32(270,359,271), Vec3i32(436,361,275), Vec3i32(273,275,361), Vec3i32(360,437,359), Vec3i32(277,287,276), Vec3i32(151,278,277), Vec3i32(280,279,289), Vec3i32(150,280,281), Vec3i32(436,438,439), Vec3i32(439,285,140), Vec3i32(90,92,432), Vec3i32(440,432,92), Vec3i32(282,272,291), Vec3i32(441,282,442), Vec3i32(284,293,274), Vec3i32(443,438,284), Vec3i32(278,432,286), Vec3i32(286,299,265), Vec3i32(281,288,433), Vec3i32(288,268,301), Vec3i32(0,433,89), Vec3i32(444,89,433), Vec3i32(435,445,442), Vec3i32(445,134,283), Vec3i32(439,446,436), Vec3i32(361,436,446), Vec3i32(442,290,435), Vec3i32(271,435,290), Vec3i32(438,436,292), Vec3i32(275,292,436), Vec3i32(445,435,447), Vec3i32(359,447,435), Vec3i32(286,287,278), Vec3i32(277,278,287), Vec3i32(288,281,289), Vec3i32(280,289,281), Vec3i32(145,152,430), Vec3i32(443,430,152), Vec3i32(148,429,154), Vec3i32(441,154,429), Vec3i32(424,430,294), Vec3i32(294,307,276), Vec3i32(423,296,429), Vec3i32(296,279,305), Vec3i32(425,440,100), Vec3i32(92,100,440), Vec3i32(290,442,291), Vec3i32(282,291,442), Vec3i32(292,293,438), Vec3i32(284,438,293), Vec3i32(298,320,241), Vec3i32(432,440,298), Vec3i32(300,236,322), Vec3i32(433,300,444), Vec3i32(426,101,444), Vec3i32(89,444,101), Vec3i32(107,448,302), Vec3i32(302,79,54), Vec3i32(78,31,343), Vec3i32(107,78,448), Vec3i32(75,79,448), Vec3i32(302,448,79), Vec3i32(78,343,448), Vec3i32(75,448,343), Vec3i32(427,418,259), Vec3i32(425,259,418), Vec3i32(428,262,417), Vec3i32(426,417,262), Vec3i32(437,449,359), Vec3i32(447,359,449), Vec3i32(434,361,450), Vec3i32(446,450,361), Vec3i32(32,33,397), Vec3i32(78,33,32), Vec3i32(53,303,54), Vec3i32(302,54,303), Vec3i32(152,153,443), Vec3i32(438,443,153), Vec3i32(429,304,441), Vec3i32(282,441,304), Vec3i32(430,443,306), Vec3i32(284,306,443), Vec3i32(154,441,155), Vec3i32(442,155,441), Vec3i32(298,299,432), Vec3i32(286,432,299), Vec3i32(300,433,301), Vec3i32(288,301,433), Vec3i32(185,451,308), Vec3i32(308,74,7), Vec3i32(73,15,337), Vec3i32(185,73,451), Vec3i32(35,74,451), Vec3i32(308,451,74), Vec3i32(73,337,451), Vec3i32(35,451,337), Vec3i32(158,452,310), Vec3i32(310,72,42), Vec3i32(70,22,341), Vec3i32(158,70,452), Vec3i32(66,72,452), Vec3i32(310,452,72), Vec3i32(70,341,452), Vec3i32(66,452,341), Vec3i32(313,327,314), Vec3i32(315,314,327), Vec3i32(316,317,326), Vec3i32(318,326,317), Vec3i32(15,156,311), Vec3i32(356,311,156), Vec3i32(7,312,157), Vec3i32(358,157,312), Vec3i32(211,9,327), Vec3i32(364,327,9), Vec3i32(38,326,94), Vec3i32(363,94,326), Vec3i32(294,295,424), Vec3i32(264,424,295), Vec3i32(296,423,297), Vec3i32(267,297,423), Vec3i32(262,149,426), Vec3i32(101,426,149), Vec3i32(258,319,425), Vec3i32(440,425,319), Vec3i32(261,426,321), Vec3i32(444,321,426), Vec3i32(259,425,146), Vec3i32(100,146,425), Vec3i32(306,307,430), Vec3i32(294,430,307), Vec3i32(304,429,305), Vec3i32(296,305,429), Vec3i32(319,320,440), Vec3i32(298,440,320), Vec3i32(321,444,322), Vec3i32(300,322,444), Vec3i32(445,283,442), Vec3i32(155,442,283), Vec3i32(439,438,285), Vec3i32(153,285,438), Vec3i32(17,68,18), Vec3i32(21,18,68), Vec3i32(46,184,47), Vec3i32(221,47,184), Vec3i32(102,95,363), Vec3i32(94,363,95), Vec3i32(9,11,364), Vec3i32(103,364,11), Vec3i32(6,323,357), Vec3i32(370,357,323), Vec3i32(371,324,355), Vec3i32(208,355,324), Vec3i32(270,363,325), Vec3i32(326,325,363), Vec3i32(327,364,328), Vec3i32(273,328,364), Vec3i32(0,2,39), Vec3i32(12,39,2), Vec3i32(90,93,91), Vec3i32(40,91,93), Vec3i32(14,16,17), Vec3i32(73,17,16), Vec3i32(45,309,7), Vec3i32(308,7,309), Vec3i32(12,71,39), Vec3i32(70,39,71), Vec3i32(40,41,42), Vec3i32(310,42,41), Vec3i32(97,98,63), Vec3i32(14,63,98), Vec3i32(3,5,7), Vec3i32(45,7,5), Vec3i32(118,377,329), Vec3i32(330,329,377), Vec3i32(331,372,332), Vec3i32(86,332,372), Vec3i32(333,376,334), Vec3i32(335,334,376), Vec3i32(115,373,336), Vec3i32(169,336,373), Vec3i32(167,166,380), Vec3i32(330,380,166), Vec3i32(80,81,382), Vec3i32(335,382,81), Vec3i32(86,385,81), Vec3i32(168,81,385), Vec3i32(169,384,82), Vec3i32(87,82,384), Vec3i32(159,88,372), Vec3i32(87,372,88), Vec3i32(163,164,376), Vec3i32(167,376,164), Vec3i32(24,26,377), Vec3i32(80,377,26), Vec3i32(56,57,373), Vec3i32(168,373,57), Vec3i32(32,397,30), Vec3i32(29,30,397), Vec3i32(58,60,53), Vec3i32(303,53,60), Vec3i32(205,181,119), Vec3i32(118,119,181), Vec3i32(163,175,165), Vec3i32(122,165,175), Vec3i32(453,454,455), Vec3i32(454,456,455), Vec3i32(457,455,456), Vec3i32(458,455,457), Vec3i32(459,455,458), Vec3i32(460,455,459), Vec3i32(461,462,463), Vec3i32(464,465,466), Vec3i32(467,468,469), Vec3i32(470,471,472), Vec3i32(465,473,474), Vec3i32(475,476,477), Vec3i32(478,479,480), Vec3i32(481,482,478), Vec3i32(483,484,481), Vec3i32(485,486,483), Vec3i32(487,488,485), Vec3i32(489,490,487), Vec3i32(491,492,489), Vec3i32(493,494,491), Vec3i32(495,496,493), Vec3i32(497,498,495), Vec3i32(499,500,497), Vec3i32(501,502,499), Vec3i32(503,504,501), Vec3i32(505,504,503), Vec3i32(506,504,505), Vec3i32(507,504,506), Vec3i32(508,504,507), Vec3i32(509,504,508), Vec3i32(510,504,509), Vec3i32(511,504,510), Vec3i32(512,504,511), Vec3i32(513,504,512), Vec3i32(514,504,513), Vec3i32(476,515,516), Vec3i32(517,518,519), Vec3i32(520,517,521), Vec3i32(518,522,523), Vec3i32(522,480,479), Vec3i32(524,525,526), Vec3i32(468,470,527), Vec3i32(525,467,528), Vec3i32(529,475,530), Vec3i32(531,532,533), Vec3i32(534,531,535), Vec3i32(536,537,538), Vec3i32(473,539,540), Vec3i32(539,536,541), Vec3i32(537,534,542), Vec3i32(471,520,543), Vec3i32(532,529,544), Vec3i32(545,524,546), Vec3i32(453,461,547), Vec3i32(463,464,548), Vec3i32(523,549,504), Vec3i32(527,550,551), Vec3i32(519,552,553), Vec3i32(521,554,555), Vec3i32(466,556,557), Vec3i32(469,558,559), Vec3i32(528,560,561), Vec3i32(477,562,563), Vec3i32(543,564,565), Vec3i32(535,566,567), Vec3i32(530,568,569), Vec3i32(540,570,571), Vec3i32(474,572,573), Vec3i32(542,574,575), Vec3i32(538,576,577), Vec3i32(541,578,579), Vec3i32(472,580,581), Vec3i32(526,582,583), Vec3i32(533,584,585), Vec3i32(544,586,587), Vec3i32(516,545,588), Vec3i32(588,589,590), Vec3i32(455,460,4), Vec3i32(591,592,63), Vec3i32(462,455,4), Vec3i32(592,547,63), Vec3i32(547,548,63), Vec3i32(465,462,4), Vec3i32(548,557,63), Vec3i32(127,124,501), Vec3i32(127,501,499), Vec3i32(505,503,124), Vec3i32(124,126,507), Vec3i32(124,507,506), Vec3i32(509,508,126), Vec3i32(126,134,512), Vec3i32(126,512,511), Vec3i32(510,509,126), Vec3i32(128,127,493), Vec3i32(128,493,491), Vec3i32(497,495,127), Vec3i32(489,487,128), Vec3i32(140,128,483), Vec3i32(140,483,481), Vec3i32(487,485,128), Vec3i32(478,480,140), Vec3i32(480,522,140), Vec3i32(514,513,134), Vec3i32(504,514,134), Vec3i32(551,581,437), Vec3i32(471,470,434), Vec3i32(445,447,555), Vec3i32(445,555,553), Vec3i32(134,445,553), Vec3i32(134,553,504), Vec3i32(446,439,518), Vec3i32(446,518,517), Vec3i32(439,140,522), Vec3i32(439,522,518), Vec3i32(515,476,358), Vec3i32(563,588,356), Vec3i32(557,573,63), Vec3i32(473,465,4), Vec3i32(437,360,559), Vec3i32(437,559,551), Vec3i32(360,371,561), Vec3i32(360,561,559), Vec3i32(362,434,470), Vec3i32(362,470,468), Vec3i32(370,362,468), Vec3i32(370,468,467), Vec3i32(499,497,127), Vec3i32(506,505,124), Vec3i32(495,493,127), Vec3i32(513,512,134), Vec3i32(481,478,140), Vec3i32(447,449,565), Vec3i32(447,565,555), Vec3i32(450,446,517), Vec3i32(450,517,520), Vec3i32(356,156,569), Vec3i32(356,569,563), Vec3i32(157,358,476), Vec3i32(157,476,475), Vec3i32(357,370,467), Vec3i32(357,467,525), Vec3i32(371,355,583), Vec3i32(371,583,561), Vec3i32(460,459,4), Vec3i32(63,62,593), Vec3i32(63,593,591), Vec3i32(62,4,459), Vec3i32(62,459,458), Vec3i32(532,531,104), Vec3i32(531,534,104), Vec3i32(567,585,105), Vec3i32(575,567,105), Vec3i32(4,3,539), Vec3i32(4,539,473), Vec3i32(536,539,3), Vec3i32(97,63,573), Vec3i32(97,573,571), Vec3i32(571,579,97), Vec3i32(99,97,579), Vec3i32(99,579,577), Vec3i32(105,99,577), Vec3i32(105,577,575), Vec3i32(96,104,534), Vec3i32(96,534,537), Vec3i32(3,96,537), Vec3i32(3,537,536), Vec3i32(503,501,124), Vec3i32(508,507,126), Vec3i32(491,489,128), Vec3i32(511,510,126), Vec3i32(485,483,128), Vec3i32(434,450,520), Vec3i32(434,520,471), Vec3i32(449,437,581), Vec3i32(449,581,565), Vec3i32(156,105,585), Vec3i32(156,585,587), Vec3i32(587,569,156), Vec3i32(104,157,529), Vec3i32(104,529,532), Vec3i32(475,529,157), Vec3i32(590,583,355), Vec3i32(355,356,588), Vec3i32(355,588,590), Vec3i32(358,357,524), Vec3i32(358,524,515), Vec3i32(525,524,357), Vec3i32(458,457,62), Vec3i32(457,593,62), Vec3i32(479,478,482), Vec3i32(479,504,549), Vec3i32(479,482,504), Vec3i32(482,481,484), Vec3i32(472,551,550), Vec3i32(581,551,472), Vec3i32(482,484,504), Vec3i32(484,483,486), Vec3i32(523,553,552), Vec3i32(504,553,523), Vec3i32(540,573,572), Vec3i32(571,573,540), Vec3i32(544,585,584), Vec3i32(587,585,544), Vec3i32(542,577,576), Vec3i32(575,577,542), Vec3i32(526,590,589), Vec3i32(583,590,526), Vec3i32(535,575,574), Vec3i32(567,575,535), Vec3i32(533,567,566), Vec3i32(585,567,533), Vec3i32(538,579,578), Vec3i32(577,579,538), Vec3i32(543,581,580), Vec3i32(565,581,543), Vec3i32(477,569,568), Vec3i32(563,569,477), Vec3i32(530,587,586), Vec3i32(569,587,530), Vec3i32(541,571,570), Vec3i32(579,571,541), Vec3i32(528,583,582), Vec3i32(561,583,528), Vec3i32(591,453,592), Vec3i32(547,592,453), Vec3i32(521,565,564), Vec3i32(555,565,521), Vec3i32(474,557,556), Vec3i32(573,557,474), Vec3i32(516,563,562), Vec3i32(588,563,516), Vec3i32(519,555,554), Vec3i32(553,555,519), Vec3i32(527,559,558), Vec3i32(551,559,527), Vec3i32(469,561,560), Vec3i32(559,561,469), Vec3i32(462,461,455), Vec3i32(453,455,461), Vec3i32(461,463,547), Vec3i32(548,547,463), Vec3i32(465,464,462), Vec3i32(463,462,464), Vec3i32(464,466,548), Vec3i32(557,548,466), Vec3i32(469,560,467), Vec3i32(528,467,560), Vec3i32(472,550,470), Vec3i32(527,470,550), Vec3i32(474,556,465), Vec3i32(466,465,556), Vec3i32(477,568,475), Vec3i32(530,475,568), Vec3i32(516,562,476), Vec3i32(477,476,562), Vec3i32(519,554,517), Vec3i32(521,517,554), Vec3i32(521,564,520), Vec3i32(543,520,564), Vec3i32(523,552,518), Vec3i32(519,518,552), Vec3i32(479,549,522), Vec3i32(523,522,549), Vec3i32(526,589,524), Vec3i32(589,546,524), Vec3i32(527,558,468), Vec3i32(469,468,558), Vec3i32(528,582,525), Vec3i32(526,525,582), Vec3i32(530,586,529), Vec3i32(544,529,586), Vec3i32(533,566,531), Vec3i32(535,531,566), Vec3i32(535,574,534), Vec3i32(542,534,574), Vec3i32(538,578,536), Vec3i32(541,536,578), Vec3i32(540,572,473), Vec3i32(474,473,572), Vec3i32(541,570,539), Vec3i32(540,539,570), Vec3i32(542,576,537), Vec3i32(538,537,576), Vec3i32(543,580,471), Vec3i32(472,471,580), Vec3i32(544,584,532), Vec3i32(533,532,584), Vec3i32(524,545,515), Vec3i32(516,515,545), Vec3i32(545,546,588), Vec3i32(589,588,546), Vec3i32(453,591,454), Vec3i32(593,454,591), Vec3i32(484,486,504), Vec3i32(486,485,488), Vec3i32(486,488,504), Vec3i32(488,487,490), Vec3i32(488,490,504), Vec3i32(490,489,492), Vec3i32(490,492,504), Vec3i32(492,491,494), Vec3i32(492,494,504), Vec3i32(494,493,496), Vec3i32(494,496,504), Vec3i32(496,495,498), Vec3i32(496,498,504), Vec3i32(498,497,500), Vec3i32(498,500,504), Vec3i32(500,499,502), Vec3i32(500,502,504), Vec3i32(501,504,502), Vec3i32(454,593,456), Vec3i32(457,456,593), Vec3i32(594,595,596), Vec3i32(597,598,594), Vec3i32(599,597,594), Vec3i32(600,599,594), Vec3i32(601,600,594), Vec3i32(602,601,594), Vec3i32(603,602,594), Vec3i32(604,603,594), Vec3i32(605,604,594), Vec3i32(606,607,608), Vec3i32(609,606,608), Vec3i32(610,609,608), Vec3i32(611,610,608), Vec3i32(612,611,608), Vec3i32(613,612,608), Vec3i32(614,613,608), Vec3i32(615,614,608), Vec3i32(616,615,608), Vec3i32(617,616,608), Vec3i32(618,617,608), Vec3i32(619,618,608), Vec3i32(620,619,608), Vec3i32(596,608,607), Vec3i32(595,594,598), Vec3i32(608,596,595), Vec3i32(605,594,91), Vec3i32(91,338,602), Vec3i32(91,602,603), Vec3i32(598,597,1), Vec3i32(594,596,91), Vec3i32(608,595,1), Vec3i32(595,598,1), Vec3i32(616,617,392), Vec3i32(610,611,394), Vec3i32(419,421,613), Vec3i32(419,613,614), Vec3i32(422,427,607), Vec3i32(422,607,606), Vec3i32(427,91,596), Vec3i32(427,596,607), Vec3i32(428,420,619), Vec3i32(428,619,620), Vec3i32(1,428,620), Vec3i32(1,620,608), Vec3i32(420,409,618), Vec3i32(420,618,619), Vec3i32(411,422,606), Vec3i32(411,606,609), Vec3i32(398,419,614), Vec3i32(398,614,615), Vec3i32(421,400,612), Vec3i32(421,612,613), Vec3i32(409,392,617), Vec3i32(409,617,618), Vec3i32(394,411,609), Vec3i32(394,609,610), Vec3i32(604,605,91), Vec3i32(338,1,599), Vec3i32(338,599,600), Vec3i32(392,398,615), Vec3i32(392,615,616), Vec3i32(400,394,611), Vec3i32(400,611,612), Vec3i32(603,604,91), Vec3i32(601,602,338), Vec3i32(597,599,1), Vec3i32(600,601,338) }; break; case TestMesh::gt2_teeth: - vertices = std::vector{ - Vec3d(15.8899993896484,19.444055557251,2.67489433288574), Vec3d(15.9129991531372,19.1590557098389,2.67489433288574), Vec3d(15.9039993286133,19.1500549316406,2.67489433288574), Vec3d(15.9489994049072,19.2490558624268,2.67489433288574), Vec3d(15.9579992294312,19.3570556640625,2.67489433288574), Vec3d(15.8819999694824,18.690055847168,2.67489433288574), Vec3d(15.8319997787476,17.7460556030273,2.67489433288574), Vec3d(15.8489999771118,18.819055557251,2.67489433288574), Vec3d(15.8589992523193,17.7190551757812,2.67489433288574), Vec3d(15.8769998550415,19.0490550994873,2.67489433288574), Vec3d(15.7529993057251,17.8080558776855,2.67489433288574), Vec3d(15.7869997024536,19.5010547637939,2.67489433288574), Vec3d(14.0329990386963,18.7170543670654,2.67489433288574), Vec3d(13.9599990844727,18.7460556030273,2.67489433288574), Vec3d(13.9869995117188,20.2840557098389,2.67489433288574), Vec3d(14.2029991149902,20.149055480957,2.67489433288574), Vec3d(14.1939992904663,19.9560546875,2.67489433288574), Vec3d(14.1939992904663,20.1670551300049,2.67489433288574), Vec3d(14.2119998931885,20.0590553283691,2.67489433288574), Vec3d(12.1899995803833,19.1840553283691,2.67489433288574), Vec3d(12.096999168396,19.1950550079346,2.67489433288574), Vec3d(12.1099996566772,20.6690559387207,2.67489433288574), Vec3d(11.382999420166,19.9750556945801,2.67489433288574), Vec3d(11.2599992752075,19.2490558624268,2.67489433288574), Vec3d(11.2369995117188,19.9320545196533,2.67489433288574), Vec3d(11.5349998474121,20.0640544891357,2.67489433288574), Vec3d(11.6259994506836,20.1550559997559,2.67489433288574), Vec3d(11.6829986572266,20.2390556335449,2.67489433288574), Vec3d(11.7369995117188,20.3570556640625,2.67489433288574), Vec3d(11.8449993133545,20.645055770874,2.67489433288574), Vec3d(11.7729988098145,20.4640560150146,2.67489433288574), Vec3d(11.7799987792969,20.5370559692383,9.41389465332031), Vec3d(11.7639999389648,20.4470558166504,2.67489433288574), Vec3d(11.9559993743896,20.6810550689697,2.67489433288574), Vec3d(12.3079996109009,20.6020545959473,2.67489433288574), Vec3d(12.1959991455078,19.1860542297363,2.67489433288574), Vec3d(12.2059993743896,20.6540546417236,2.67489433288574), Vec3d(12.3489990234375,20.3740558624268,2.67489433288574), Vec3d(12.3579998016357,20.2750549316406,2.67489433288574), Vec3d(12.3669996261597,20.266056060791,2.67489433288574), Vec3d(12.3849992752075,20.1670551300049,2.67489433288574), Vec3d(12.4269990921021,20.0680541992188,2.67489433288574), Vec3d(12.5029993057251,19.9540557861328,2.67489433288574), Vec3d(12.6169996261597,19.8550548553467,2.67489433288574), Vec3d(12.7449989318848,19.7800559997559,2.67489433288574), Vec3d(12.7629995346069,19.7800559997559,2.67489433288574), Vec3d(12.8799991607666,19.7350559234619,2.67489433288574), Vec3d(13.0369997024536,19.7250556945801,2.67489433288574), Vec3d(13.0149993896484,19.0340557098389,2.67489433288574), Vec3d(11.1699991226196,19.2580547332764,2.67489433288574), Vec3d(11.0959987640381,19.2580547332764,2.67489433288574), Vec3d(11.1209993362427,19.9230556488037,2.67489433288574), Vec3d(13.0599994659424,19.024055480957,2.67489433288574), Vec3d(14.9049997329712,18.3170547485352,2.67489433288574), Vec3d(14.8779993057251,18.3400554656982,2.67489433288574), Vec3d(14.8779993057251,19.149055480957,2.67489433288574), Vec3d(13.3039989471436,19.77805519104,2.67489433288574), Vec3d(13.1589994430542,18.9890556335449,2.67489433288574), Vec3d(13.1559991836548,19.7350559234619,2.67489433288574), Vec3d(13.4269990921021,19.8600559234619,2.67489433288574), Vec3d(13.5339994430542,19.9700546264648,2.67389440536499), Vec3d(13.6359996795654,20.1220550537109,2.67489433288574), Vec3d(13.6359996795654,20.1400547027588,2.67489433288574), Vec3d(13.6719989776611,20.2210559844971,2.67489433288574), Vec3d(13.6899995803833,20.2300548553467,2.67489433288574), Vec3d(13.7509994506836,20.3010559082031,2.67489433288574), Vec3d(13.8539991378784,20.3180541992188,2.67489433288574), Vec3d(14.8329992294312,18.3580551147461,2.67489433288574), Vec3d(14.1849994659424,19.8530559539795,2.67489433288574), Vec3d(14.0769996643066,18.7000541687012,2.67489433288574), Vec3d(14.1099996566772,20.2400550842285,2.67489433288574), Vec3d(14.2009992599487,19.6230545043945,2.67489433288574), Vec3d(14.2729997634888,19.4670543670654,2.67489433288574), Vec3d(14.3379993438721,19.3790550231934,2.67489433288574), Vec3d(14.4549999237061,19.2770557403564,2.67489433288574), Vec3d(14.5899991989136,19.2040557861328,2.67489433288574), Vec3d(14.6079998016357,19.2040557861328,2.67489433288574), Vec3d(14.7209997177124,19.1600551605225,2.67489433288574), Vec3d(15.1379995346069,19.210054397583,2.67489433288574), Vec3d(14.9949998855591,18.2680549621582,2.67489433288574), Vec3d(15.0029993057251,19.1580543518066,2.67489433288574), Vec3d(15.2369995117188,19.2760543823242,2.67489433288574), Vec3d(15.3779993057251,19.4060554504395,2.67489433288574), Vec3d(15.4539995193481,19.520055770874,2.67489433288574), Vec3d(15.471999168396,19.52805519104,2.67489433288574), Vec3d(15.5449991226196,19.5830554962158,2.67489433288574), Vec3d(15.6529998779297,19.573055267334,2.67489433288574), Vec3d(15.7059993743896,17.8360557556152,2.67489433288574), Vec3d(15.9449996948242,18.5560550689697,2.67489433288574), Vec3d(15.8589992523193,18.9380550384521,2.67489433288574), Vec3d(14.9589996337891,18.2950553894043,2.67489433288574), Vec3d(15.7779998779297,19.5100555419922,2.67489433288574), Vec3d(14.0049991607666,20.2750549316406,2.67489433288574), Vec3d(12.3489990234375,20.5000553131104,2.67489433288574), Vec3d(13.0689992904663,19.0150547027588,2.67489433288574), Vec3d(13.0999994277954,19.0100555419922,2.67489433288574), Vec3d(15.9489994049072,19.3670558929443,9.41489505767822), Vec3d(15.9489994049072,19.2490558624268,9.41489505767822), Vec3d(15.75,17.8080558776855,9.41489505767822), Vec3d(15.6639995574951,19.5710544586182,9.41489505767822), Vec3d(15.5709991455078,17.9260559082031,9.41489505767822), Vec3d(15.8769998550415,18.690055847168,9.41489505767822), Vec3d(15.8499994277954,18.8170547485352,9.41489505767822), Vec3d(15.9459991455078,18.5520553588867,9.41489505767822), Vec3d(15.914999961853,17.6890544891357,9.41489505767822), Vec3d(15.3999996185303,19.4290542602539,9.41489505767822), Vec3d(15.3099994659424,19.339054107666,9.41489505767822), Vec3d(15.3729991912842,18.0440559387207,9.41489505767822), Vec3d(15.4579992294312,19.5170555114746,9.41489505767822), Vec3d(15.5469999313354,19.5820541381836,9.41489505767822), Vec3d(13.2309989929199,19.7610549926758,9.41489505767822), Vec3d(13.168999671936,19.7360553741455,9.41489505767822), Vec3d(13.096999168396,19.0140552520752,9.41489505767822), Vec3d(13.1999988555908,18.9870548248291,9.41489505767822), Vec3d(15.1399993896484,19.2080554962158,9.41489505767822), Vec3d(15.0159997940063,19.1600551605225,9.41489505767822), Vec3d(14.9859991073608,18.2770557403564,9.41489505767822), Vec3d(15.1749992370605,18.1690559387207,9.41489505767822), Vec3d(15.9039993286133,19.1320552825928,9.41489505767822), Vec3d(15.8949995040894,19.4460544586182,9.41489505767822), Vec3d(15.8769998550415,19.0420551300049,9.41489505767822), Vec3d(12.2169990539551,20.6500549316406,9.41489505767822), Vec3d(11.9379997253418,20.6810550689697,9.41489505767822), Vec3d(11.8629989624023,19.2130546569824,9.41489505767822), Vec3d(12.096999168396,19.1950550079346,9.41489505767822), Vec3d(14.1669998168945,18.6640548706055,9.41489505767822), Vec3d(14.1039991378784,20.2460556030273,9.41489505767822), Vec3d(13.9849996566772,18.7360553741455,9.41489505767822), Vec3d(14.7349996566772,19.1590557098389,9.41489505767822), Vec3d(14.5849990844727,19.2050552368164,9.41489505767822), Vec3d(14.5719995498657,18.4850559234619,9.41489505767822), Vec3d(14.1939992904663,19.6760559082031,9.41489505767822), Vec3d(14.1849994659424,19.9330558776855,9.41489505767822), Vec3d(14.1759996414185,18.6640548706055,9.41489505767822), Vec3d(14.261999130249,19.4890556335449,9.41489505767822), Vec3d(14.3539991378784,19.3610553741455,9.41489505767822), Vec3d(14.3559989929199,18.5830554962158,9.41489505767822), Vec3d(11.6039991378784,20.1250553131104,9.41489505767822), Vec3d(11.5209999084473,20.0520553588867,9.41489505767822), Vec3d(11.4209995269775,19.2480545043945,9.41489505767822), Vec3d(11.6989994049072,20.2690544128418,9.41389465332031), Vec3d(11.7609996795654,20.4310550689697,9.41489505767822), Vec3d(11.8359994888306,19.2130546569824,9.41489505767822), Vec3d(14.1889991760254,20.1710548400879,9.41489505767822), Vec3d(13.9689998626709,20.2840557098389,9.41489505767822), Vec3d(13.8739995956421,20.315055847168,9.41489505767822), Vec3d(13.7799997329712,18.8080558776855,9.41489505767822), Vec3d(13.9869995117188,20.2750549316406,9.41489505767822), Vec3d(12.3129997253418,20.5980548858643,9.41489505767822), Vec3d(12.3399991989136,20.5090560913086,9.41489505767822), Vec3d(12.3489990234375,20.3830547332764,9.41489505767822), Vec3d(12.3599996566772,20.2680549621582,9.41489505767822), Vec3d(12.3849992752075,20.1850547790527,9.41489505767822), Vec3d(12.3849992752075,20.1670551300049,9.41489505767822), Vec3d(12.4249992370605,20.065055847168,9.41489505767822), Vec3d(12.4729995727539,19.1350555419922,9.41489505767822), Vec3d(14.4399995803833,19.2900543212891,9.41489505767822), Vec3d(14.3649997711182,18.5740547180176,9.41489505767822), Vec3d(13.5729999542236,20.0310554504395,9.41489505767822), Vec3d(13.4889993667603,19.9140548706055,9.41489505767822), Vec3d(13.5639991760254,18.8710556030273,9.41489505767822), Vec3d(13.6389999389648,20.1310558319092,9.41489505767822), Vec3d(13.6719989776611,20.2130546569824,9.41489505767822), Vec3d(13.75,20.3020553588867,9.41489505767822), Vec3d(12.7399997711182,19.7810554504395,9.41489505767822), Vec3d(12.6189994812012,19.8520545959473,9.41489505767822), Vec3d(12.5799999237061,19.1200542449951,9.41489505767822), Vec3d(12.8349990844727,19.069055557251,9.41489505767822), Vec3d(11.2669992446899,19.9350547790527,9.41489505767822), Vec3d(11.1029987335205,19.9230556488037,9.41489505767822), Vec3d(11.0209999084473,19.2600555419922,9.41489505767822), Vec3d(11.3819999694824,19.9710559844971,9.41489505767822), Vec3d(13.418999671936,19.8530559539795,9.41489505767822), Vec3d(13.4329996109009,18.9160556793213,9.41489505767822), Vec3d(11.8399991989136,20.6430549621582,9.41489505767822), Vec3d(13.3119993209839,19.7800559997559,9.41489505767822), Vec3d(15.2189998626709,19.2600555419922,9.41489505767822), Vec3d(15.1839990615845,18.1600551605225,9.41489505767822), Vec3d(15.3639993667603,18.0520553588867,9.41489505767822), Vec3d(13.0189990997314,19.7250556945801,9.41489505767822), Vec3d(12.8949995040894,19.7350559234619,9.41489505767822), Vec3d(15.9039993286133,19.1500549316406,9.41489505767822), Vec3d(15.7699995040894,19.5140552520752,9.41489505767822), Vec3d(15.8589992523193,18.9340553283691,9.41489505767822), Vec3d(14.1939992904663,19.9510555267334,9.41489505767822), Vec3d(14.2119998931885,20.0630550384521,9.41489505767822), Vec3d(14.8589992523193,19.149055480957,9.41489505767822), Vec3d(14.8159999847412,18.3670558929443,9.41489505767822), Vec3d(14.8959999084473,18.3220558166504,9.41489505767822), Vec3d(12.5189990997314,19.9360542297363,9.41489505767822), Vec3d(11.0209999084473,19.9290542602539,9.41489505767822), Vec3d(11.0209999084473,19.2530555725098,2.67489433288574), Vec3d(11.0209999084473,19.9300556182861,2.67489433288574), Vec3d(15.9799995422363,18.505931854248,5.58724021911621), Vec3d(15.9799995422363,18.5044555664062,9.41489505767822), Vec3d(15.9799995422363,18.5041732788086,2.67489433288574), Vec3d(15.9799995422363,18.1684837341309,2.67489433288574), Vec3d(15.9799995422363,18.1288299560547,9.41489505767822), Vec3d(15.9799995422363,17.9876575469971,2.67489433288574), Vec3d(15.9799995422363,17.6247596740723,3.91620373725891), Vec3d(15.9799995422363,17.6247596740723,2.67489433288574), Vec3d(15.9799995422363,17.6254329681396,4.32245063781738), Vec3d(15.9799995422363,17.8920269012451,9.41489505767822), Vec3d(15.9799995422363,17.8795108795166,2.67489433288574), Vec3d(15.9799995422363,17.629810333252,4.58585262298584), Vec3d(15.9799995422363,17.6336059570312,5.27938556671143), Vec3d(15.9799995422363,17.8311748504639,2.67489433288574), Vec3d(15.9799995422363,17.638355255127,9.41489505767822), Vec3d(15.9799995422363,17.6346111297607,5.98653984069824), Vec3d(15.9799995422363,17.8728256225586,2.67489433288574), Vec3d(15.9799995422363,18.2221603393555,2.67489433288574) + vertices = std::vector{ + Vec3f(15.8899993896484,19.444055557251,2.67489433288574), Vec3f(15.9129991531372,19.1590557098389,2.67489433288574), Vec3f(15.9039993286133,19.1500549316406,2.67489433288574), Vec3f(15.9489994049072,19.2490558624268,2.67489433288574), Vec3f(15.9579992294312,19.3570556640625,2.67489433288574), Vec3f(15.8819999694824,18.690055847168,2.67489433288574), Vec3f(15.8319997787476,17.7460556030273,2.67489433288574), Vec3f(15.8489999771118,18.819055557251,2.67489433288574), Vec3f(15.8589992523193,17.7190551757812,2.67489433288574), Vec3f(15.8769998550415,19.0490550994873,2.67489433288574), Vec3f(15.7529993057251,17.8080558776855,2.67489433288574), Vec3f(15.7869997024536,19.5010547637939,2.67489433288574), Vec3f(14.0329990386963,18.7170543670654,2.67489433288574), Vec3f(13.9599990844727,18.7460556030273,2.67489433288574), Vec3f(13.9869995117188,20.2840557098389,2.67489433288574), Vec3f(14.2029991149902,20.149055480957,2.67489433288574), Vec3f(14.1939992904663,19.9560546875,2.67489433288574), Vec3f(14.1939992904663,20.1670551300049,2.67489433288574), Vec3f(14.2119998931885,20.0590553283691,2.67489433288574), Vec3f(12.1899995803833,19.1840553283691,2.67489433288574), Vec3f(12.096999168396,19.1950550079346,2.67489433288574), Vec3f(12.1099996566772,20.6690559387207,2.67489433288574), Vec3f(11.382999420166,19.9750556945801,2.67489433288574), Vec3f(11.2599992752075,19.2490558624268,2.67489433288574), Vec3f(11.2369995117188,19.9320545196533,2.67489433288574), Vec3f(11.5349998474121,20.0640544891357,2.67489433288574), Vec3f(11.6259994506836,20.1550559997559,2.67489433288574), Vec3f(11.6829986572266,20.2390556335449,2.67489433288574), Vec3f(11.7369995117188,20.3570556640625,2.67489433288574), Vec3f(11.8449993133545,20.645055770874,2.67489433288574), Vec3f(11.7729988098145,20.4640560150146,2.67489433288574), Vec3f(11.7799987792969,20.5370559692383,9.41389465332031), Vec3f(11.7639999389648,20.4470558166504,2.67489433288574), Vec3f(11.9559993743896,20.6810550689697,2.67489433288574), Vec3f(12.3079996109009,20.6020545959473,2.67489433288574), Vec3f(12.1959991455078,19.1860542297363,2.67489433288574), Vec3f(12.2059993743896,20.6540546417236,2.67489433288574), Vec3f(12.3489990234375,20.3740558624268,2.67489433288574), Vec3f(12.3579998016357,20.2750549316406,2.67489433288574), Vec3f(12.3669996261597,20.266056060791,2.67489433288574), Vec3f(12.3849992752075,20.1670551300049,2.67489433288574), Vec3f(12.4269990921021,20.0680541992188,2.67489433288574), Vec3f(12.5029993057251,19.9540557861328,2.67489433288574), Vec3f(12.6169996261597,19.8550548553467,2.67489433288574), Vec3f(12.7449989318848,19.7800559997559,2.67489433288574), Vec3f(12.7629995346069,19.7800559997559,2.67489433288574), Vec3f(12.8799991607666,19.7350559234619,2.67489433288574), Vec3f(13.0369997024536,19.7250556945801,2.67489433288574), Vec3f(13.0149993896484,19.0340557098389,2.67489433288574), Vec3f(11.1699991226196,19.2580547332764,2.67489433288574), Vec3f(11.0959987640381,19.2580547332764,2.67489433288574), Vec3f(11.1209993362427,19.9230556488037,2.67489433288574), Vec3f(13.0599994659424,19.024055480957,2.67489433288574), Vec3f(14.9049997329712,18.3170547485352,2.67489433288574), Vec3f(14.8779993057251,18.3400554656982,2.67489433288574), Vec3f(14.8779993057251,19.149055480957,2.67489433288574), Vec3f(13.3039989471436,19.77805519104,2.67489433288574), Vec3f(13.1589994430542,18.9890556335449,2.67489433288574), Vec3f(13.1559991836548,19.7350559234619,2.67489433288574), Vec3f(13.4269990921021,19.8600559234619,2.67489433288574), Vec3f(13.5339994430542,19.9700546264648,2.67389440536499), Vec3f(13.6359996795654,20.1220550537109,2.67489433288574), Vec3f(13.6359996795654,20.1400547027588,2.67489433288574), Vec3f(13.6719989776611,20.2210559844971,2.67489433288574), Vec3f(13.6899995803833,20.2300548553467,2.67489433288574), Vec3f(13.7509994506836,20.3010559082031,2.67489433288574), Vec3f(13.8539991378784,20.3180541992188,2.67489433288574), Vec3f(14.8329992294312,18.3580551147461,2.67489433288574), Vec3f(14.1849994659424,19.8530559539795,2.67489433288574), Vec3f(14.0769996643066,18.7000541687012,2.67489433288574), Vec3f(14.1099996566772,20.2400550842285,2.67489433288574), Vec3f(14.2009992599487,19.6230545043945,2.67489433288574), Vec3f(14.2729997634888,19.4670543670654,2.67489433288574), Vec3f(14.3379993438721,19.3790550231934,2.67489433288574), Vec3f(14.4549999237061,19.2770557403564,2.67489433288574), Vec3f(14.5899991989136,19.2040557861328,2.67489433288574), Vec3f(14.6079998016357,19.2040557861328,2.67489433288574), Vec3f(14.7209997177124,19.1600551605225,2.67489433288574), Vec3f(15.1379995346069,19.210054397583,2.67489433288574), Vec3f(14.9949998855591,18.2680549621582,2.67489433288574), Vec3f(15.0029993057251,19.1580543518066,2.67489433288574), Vec3f(15.2369995117188,19.2760543823242,2.67489433288574), Vec3f(15.3779993057251,19.4060554504395,2.67489433288574), Vec3f(15.4539995193481,19.520055770874,2.67489433288574), Vec3f(15.471999168396,19.52805519104,2.67489433288574), Vec3f(15.5449991226196,19.5830554962158,2.67489433288574), Vec3f(15.6529998779297,19.573055267334,2.67489433288574), Vec3f(15.7059993743896,17.8360557556152,2.67489433288574), Vec3f(15.9449996948242,18.5560550689697,2.67489433288574), Vec3f(15.8589992523193,18.9380550384521,2.67489433288574), Vec3f(14.9589996337891,18.2950553894043,2.67489433288574), Vec3f(15.7779998779297,19.5100555419922,2.67489433288574), Vec3f(14.0049991607666,20.2750549316406,2.67489433288574), Vec3f(12.3489990234375,20.5000553131104,2.67489433288574), Vec3f(13.0689992904663,19.0150547027588,2.67489433288574), Vec3f(13.0999994277954,19.0100555419922,2.67489433288574), Vec3f(15.9489994049072,19.3670558929443,9.41489505767822), Vec3f(15.9489994049072,19.2490558624268,9.41489505767822), Vec3f(15.75,17.8080558776855,9.41489505767822), Vec3f(15.6639995574951,19.5710544586182,9.41489505767822), Vec3f(15.5709991455078,17.9260559082031,9.41489505767822), Vec3f(15.8769998550415,18.690055847168,9.41489505767822), Vec3f(15.8499994277954,18.8170547485352,9.41489505767822), Vec3f(15.9459991455078,18.5520553588867,9.41489505767822), Vec3f(15.914999961853,17.6890544891357,9.41489505767822), Vec3f(15.3999996185303,19.4290542602539,9.41489505767822), Vec3f(15.3099994659424,19.339054107666,9.41489505767822), Vec3f(15.3729991912842,18.0440559387207,9.41489505767822), Vec3f(15.4579992294312,19.5170555114746,9.41489505767822), Vec3f(15.5469999313354,19.5820541381836,9.41489505767822), Vec3f(13.2309989929199,19.7610549926758,9.41489505767822), Vec3f(13.168999671936,19.7360553741455,9.41489505767822), Vec3f(13.096999168396,19.0140552520752,9.41489505767822), Vec3f(13.1999988555908,18.9870548248291,9.41489505767822), Vec3f(15.1399993896484,19.2080554962158,9.41489505767822), Vec3f(15.0159997940063,19.1600551605225,9.41489505767822), Vec3f(14.9859991073608,18.2770557403564,9.41489505767822), Vec3f(15.1749992370605,18.1690559387207,9.41489505767822), Vec3f(15.9039993286133,19.1320552825928,9.41489505767822), Vec3f(15.8949995040894,19.4460544586182,9.41489505767822), Vec3f(15.8769998550415,19.0420551300049,9.41489505767822), Vec3f(12.2169990539551,20.6500549316406,9.41489505767822), Vec3f(11.9379997253418,20.6810550689697,9.41489505767822), Vec3f(11.8629989624023,19.2130546569824,9.41489505767822), Vec3f(12.096999168396,19.1950550079346,9.41489505767822), Vec3f(14.1669998168945,18.6640548706055,9.41489505767822), Vec3f(14.1039991378784,20.2460556030273,9.41489505767822), Vec3f(13.9849996566772,18.7360553741455,9.41489505767822), Vec3f(14.7349996566772,19.1590557098389,9.41489505767822), Vec3f(14.5849990844727,19.2050552368164,9.41489505767822), Vec3f(14.5719995498657,18.4850559234619,9.41489505767822), Vec3f(14.1939992904663,19.6760559082031,9.41489505767822), Vec3f(14.1849994659424,19.9330558776855,9.41489505767822), Vec3f(14.1759996414185,18.6640548706055,9.41489505767822), Vec3f(14.261999130249,19.4890556335449,9.41489505767822), Vec3f(14.3539991378784,19.3610553741455,9.41489505767822), Vec3f(14.3559989929199,18.5830554962158,9.41489505767822), Vec3f(11.6039991378784,20.1250553131104,9.41489505767822), Vec3f(11.5209999084473,20.0520553588867,9.41489505767822), Vec3f(11.4209995269775,19.2480545043945,9.41489505767822), Vec3f(11.6989994049072,20.2690544128418,9.41389465332031), Vec3f(11.7609996795654,20.4310550689697,9.41489505767822), Vec3f(11.8359994888306,19.2130546569824,9.41489505767822), Vec3f(14.1889991760254,20.1710548400879,9.41489505767822), Vec3f(13.9689998626709,20.2840557098389,9.41489505767822), Vec3f(13.8739995956421,20.315055847168,9.41489505767822), Vec3f(13.7799997329712,18.8080558776855,9.41489505767822), Vec3f(13.9869995117188,20.2750549316406,9.41489505767822), Vec3f(12.3129997253418,20.5980548858643,9.41489505767822), Vec3f(12.3399991989136,20.5090560913086,9.41489505767822), Vec3f(12.3489990234375,20.3830547332764,9.41489505767822), Vec3f(12.3599996566772,20.2680549621582,9.41489505767822), Vec3f(12.3849992752075,20.1850547790527,9.41489505767822), Vec3f(12.3849992752075,20.1670551300049,9.41489505767822), Vec3f(12.4249992370605,20.065055847168,9.41489505767822), Vec3f(12.4729995727539,19.1350555419922,9.41489505767822), Vec3f(14.4399995803833,19.2900543212891,9.41489505767822), Vec3f(14.3649997711182,18.5740547180176,9.41489505767822), Vec3f(13.5729999542236,20.0310554504395,9.41489505767822), Vec3f(13.4889993667603,19.9140548706055,9.41489505767822), Vec3f(13.5639991760254,18.8710556030273,9.41489505767822), Vec3f(13.6389999389648,20.1310558319092,9.41489505767822), Vec3f(13.6719989776611,20.2130546569824,9.41489505767822), Vec3f(13.75,20.3020553588867,9.41489505767822), Vec3f(12.7399997711182,19.7810554504395,9.41489505767822), Vec3f(12.6189994812012,19.8520545959473,9.41489505767822), Vec3f(12.5799999237061,19.1200542449951,9.41489505767822), Vec3f(12.8349990844727,19.069055557251,9.41489505767822), Vec3f(11.2669992446899,19.9350547790527,9.41489505767822), Vec3f(11.1029987335205,19.9230556488037,9.41489505767822), Vec3f(11.0209999084473,19.2600555419922,9.41489505767822), Vec3f(11.3819999694824,19.9710559844971,9.41489505767822), Vec3f(13.418999671936,19.8530559539795,9.41489505767822), Vec3f(13.4329996109009,18.9160556793213,9.41489505767822), Vec3f(11.8399991989136,20.6430549621582,9.41489505767822), Vec3f(13.3119993209839,19.7800559997559,9.41489505767822), Vec3f(15.2189998626709,19.2600555419922,9.41489505767822), Vec3f(15.1839990615845,18.1600551605225,9.41489505767822), Vec3f(15.3639993667603,18.0520553588867,9.41489505767822), Vec3f(13.0189990997314,19.7250556945801,9.41489505767822), Vec3f(12.8949995040894,19.7350559234619,9.41489505767822), Vec3f(15.9039993286133,19.1500549316406,9.41489505767822), Vec3f(15.7699995040894,19.5140552520752,9.41489505767822), Vec3f(15.8589992523193,18.9340553283691,9.41489505767822), Vec3f(14.1939992904663,19.9510555267334,9.41489505767822), Vec3f(14.2119998931885,20.0630550384521,9.41489505767822), Vec3f(14.8589992523193,19.149055480957,9.41489505767822), Vec3f(14.8159999847412,18.3670558929443,9.41489505767822), Vec3f(14.8959999084473,18.3220558166504,9.41489505767822), Vec3f(12.5189990997314,19.9360542297363,9.41489505767822), Vec3f(11.0209999084473,19.9290542602539,9.41489505767822), Vec3f(11.0209999084473,19.2530555725098,2.67489433288574), Vec3f(11.0209999084473,19.9300556182861,2.67489433288574), Vec3f(15.9799995422363,18.505931854248,5.58724021911621), Vec3f(15.9799995422363,18.5044555664062,9.41489505767822), Vec3f(15.9799995422363,18.5041732788086,2.67489433288574), Vec3f(15.9799995422363,18.1684837341309,2.67489433288574), Vec3f(15.9799995422363,18.1288299560547,9.41489505767822), Vec3f(15.9799995422363,17.9876575469971,2.67489433288574), Vec3f(15.9799995422363,17.6247596740723,3.91620373725891), Vec3f(15.9799995422363,17.6247596740723,2.67489433288574), Vec3f(15.9799995422363,17.6254329681396,4.32245063781738), Vec3f(15.9799995422363,17.8920269012451,9.41489505767822), Vec3f(15.9799995422363,17.8795108795166,2.67489433288574), Vec3f(15.9799995422363,17.629810333252,4.58585262298584), Vec3f(15.9799995422363,17.6336059570312,5.27938556671143), Vec3f(15.9799995422363,17.8311748504639,2.67489433288574), Vec3f(15.9799995422363,17.638355255127,9.41489505767822), Vec3f(15.9799995422363,17.6346111297607,5.98653984069824), Vec3f(15.9799995422363,17.8728256225586,2.67489433288574), Vec3f(15.9799995422363,18.2221603393555,2.67489433288574) }; facets = std::vector{ Vec3i32(0,1,2), Vec3i32(0,3,1), Vec3i32(0,4,3), Vec3i32(5,6,7), Vec3i32(8,6,5), Vec3i32(2,9,0), Vec3i32(6,10,11), Vec3i32(12,13,14), Vec3i32(15,16,17), Vec3i32(18,16,15), Vec3i32(19,20,21), Vec3i32(22,23,24), Vec3i32(25,23,22), Vec3i32(26,23,25), Vec3i32(27,23,26), Vec3i32(28,23,27), Vec3i32(29,30,31), Vec3i32(29,32,30), Vec3i32(29,28,32), Vec3i32(33,28,29), Vec3i32(33,23,28), Vec3i32(21,23,33), Vec3i32(20,23,21), Vec3i32(34,35,36), Vec3i32(37,35,34), Vec3i32(38,35,37), Vec3i32(39,35,38), Vec3i32(40,35,39), Vec3i32(41,35,40), Vec3i32(42,35,41), Vec3i32(43,35,42), Vec3i32(44,35,43), Vec3i32(45,35,44), Vec3i32(46,35,45), Vec3i32(47,35,46), Vec3i32(48,35,47), Vec3i32(49,50,51), Vec3i32(52,48,47), Vec3i32(23,49,24), Vec3i32(53,54,55), Vec3i32(56,57,58), Vec3i32(59,57,56), Vec3i32(60,57,59), Vec3i32(61,57,60), Vec3i32(62,57,61), Vec3i32(63,57,62), Vec3i32(64,57,63), Vec3i32(65,57,64), Vec3i32(66,57,65), Vec3i32(13,57,66), Vec3i32(54,67,55), Vec3i32(68,69,70), Vec3i32(71,69,68), Vec3i32(72,69,71), Vec3i32(73,69,72), Vec3i32(74,69,73), Vec3i32(75,69,74), Vec3i32(76,69,75), Vec3i32(77,69,76), Vec3i32(67,69,77), Vec3i32(70,16,68), Vec3i32(70,17,16), Vec3i32(78,79,80), Vec3i32(81,79,78), Vec3i32(82,79,81), Vec3i32(83,79,82), Vec3i32(84,79,83), Vec3i32(85,79,84), Vec3i32(86,79,85), Vec3i32(87,79,86), Vec3i32(88,8,5), Vec3i32(11,7,6), Vec3i32(11,89,7), Vec3i32(11,9,89), Vec3i32(11,0,9), Vec3i32(55,90,53), Vec3i32(55,79,90), Vec3i32(55,80,79), Vec3i32(91,11,10), Vec3i32(92,69,12), Vec3i32(92,70,69), Vec3i32(34,93,37), Vec3i32(47,94,52), Vec3i32(47,95,94), Vec3i32(47,57,95), Vec3i32(47,58,57), Vec3i32(51,24,49), Vec3i32(21,35,19), Vec3i32(21,36,35), Vec3i32(14,92,12), Vec3i32(86,10,87), Vec3i32(86,91,10), Vec3i32(77,55,67), Vec3i32(66,14,13), Vec3i32(96,97,4), Vec3i32(98,99,100), Vec3i32(101,102,98), Vec3i32(103,101,98), Vec3i32(104,103,98), Vec3i32(105,106,107), Vec3i32(108,105,107), Vec3i32(109,108,107), Vec3i32(100,109,107), Vec3i32(110,111,112), Vec3i32(113,110,112), Vec3i32(114,115,116), Vec3i32(117,114,116), Vec3i32(118,119,120), Vec3i32(121,122,123), Vec3i32(124,121,123), Vec3i32(125,126,127), Vec3i32(128,129,130), Vec3i32(131,132,133), Vec3i32(71,131,133), Vec3i32(134,71,133), Vec3i32(135,134,133), Vec3i32(136,135,133), Vec3i32(137,138,139), Vec3i32(140,137,139), Vec3i32(141,140,139), Vec3i32(142,31,141), Vec3i32(142,141,139), Vec3i32(143,126,132), Vec3i32(144,145,146), Vec3i32(147,144,146), Vec3i32(127,147,146), Vec3i32(148,121,124), Vec3i32(149,148,124), Vec3i32(150,149,124), Vec3i32(151,150,124), Vec3i32(152,151,124), Vec3i32(153,152,124), Vec3i32(154,153,124), Vec3i32(155,154,124), Vec3i32(129,156,157), Vec3i32(130,129,157), Vec3i32(158,159,160), Vec3i32(161,158,160), Vec3i32(162,161,160), Vec3i32(163,162,160), Vec3i32(146,163,160), Vec3i32(164,165,166), Vec3i32(167,164,166), Vec3i32(168,169,170), Vec3i32(171,168,170), Vec3i32(139,171,170), Vec3i32(159,172,173), Vec3i32(123,174,142), Vec3i32(175,110,113), Vec3i32(173,175,113), Vec3i32(106,176,177), Vec3i32(178,106,177), Vec3i32(179,180,167), Vec3i32(112,179,167), Vec3i32(175,173,172), Vec3i32(119,118,181), Vec3i32(119,181,97), Vec3i32(119,97,96), Vec3i32(182,98,102), Vec3i32(182,102,183), Vec3i32(182,183,120), Vec3i32(182,120,119), Vec3i32(143,132,184), Vec3i32(184,185,143), Vec3i32(147,127,126), Vec3i32(174,123,122), Vec3i32(159,173,160), Vec3i32(126,125,133), Vec3i32(126,133,132), Vec3i32(186,187,188), Vec3i32(186,188,116), Vec3i32(186,116,115), Vec3i32(99,98,182), Vec3i32(109,100,99), Vec3i32(106,178,107), Vec3i32(114,117,177), Vec3i32(114,177,176), Vec3i32(128,130,187), Vec3i32(128,187,186), Vec3i32(135,136,157), Vec3i32(135,157,156), Vec3i32(163,146,145), Vec3i32(164,167,180), Vec3i32(179,112,111), Vec3i32(171,139,138), Vec3i32(189,155,166), Vec3i32(189,166,165), Vec3i32(149,150,93), Vec3i32(154,155,189), Vec3i32(31,142,174), Vec3i32(114,176,78), Vec3i32(81,78,176), Vec3i32(7,89,183), Vec3i32(89,9,120), Vec3i32(89,120,183), Vec3i32(78,80,114), Vec3i32(176,106,81), Vec3i32(88,5,103), Vec3i32(183,102,7), Vec3i32(118,120,9), Vec3i32(9,2,181), Vec3i32(9,181,118), Vec3i32(115,114,80), Vec3i32(82,81,106), Vec3i32(101,103,5), Vec3i32(102,101,5), Vec3i32(5,7,102), Vec3i32(97,181,2), Vec3i32(2,1,97), Vec3i32(1,3,97), Vec3i32(80,55,115), Vec3i32(172,159,59), Vec3i32(59,56,172), Vec3i32(3,4,97), Vec3i32(4,0,96), Vec3i32(105,108,82), Vec3i32(186,115,55), Vec3i32(82,106,105), Vec3i32(83,82,108), Vec3i32(60,59,159), Vec3i32(175,172,56), Vec3i32(119,96,0), Vec3i32(0,11,119), Vec3i32(108,109,84), Vec3i32(84,83,108), Vec3i32(55,77,186), Vec3i32(56,58,110), Vec3i32(56,110,175), Vec3i32(60,159,158), Vec3i32(11,91,182), Vec3i32(182,119,11), Vec3i32(91,86,182), Vec3i32(85,84,109), Vec3i32(86,85,99), Vec3i32(128,186,77), Vec3i32(58,111,110), Vec3i32(158,161,60), Vec3i32(26,25,137), Vec3i32(138,137,25), Vec3i32(99,182,86), Vec3i32(109,99,85), Vec3i32(77,76,128), Vec3i32(58,47,111), Vec3i32(61,60,161), Vec3i32(137,140,26), Vec3i32(27,26,140), Vec3i32(25,22,138), Vec3i32(129,128,76), Vec3i32(76,75,129), Vec3i32(75,74,129), Vec3i32(74,73,156), Vec3i32(73,72,135), Vec3i32(68,16,184), Vec3i32(68,184,132), Vec3i32(16,18,185), Vec3i32(161,162,62), Vec3i32(62,61,161), Vec3i32(179,111,47), Vec3i32(171,138,22), Vec3i32(156,129,74), Vec3i32(135,156,73), Vec3i32(134,135,72), Vec3i32(72,71,134), Vec3i32(68,132,131), Vec3i32(185,184,16), Vec3i32(18,15,185), Vec3i32(63,62,162), Vec3i32(28,27,140), Vec3i32(22,24,171), Vec3i32(71,68,131), Vec3i32(15,17,143), Vec3i32(15,143,185), Vec3i32(17,70,143), Vec3i32(70,92,126), Vec3i32(162,163,64), Vec3i32(64,63,162), Vec3i32(180,179,47), Vec3i32(47,46,180), Vec3i32(140,141,28), Vec3i32(168,171,24), Vec3i32(126,143,70), Vec3i32(92,14,147), Vec3i32(147,126,92), Vec3i32(14,66,144), Vec3i32(14,144,147), Vec3i32(65,64,163), Vec3i32(66,65,145), Vec3i32(46,45,180), Vec3i32(32,28,141), Vec3i32(24,51,168), Vec3i32(145,144,66), Vec3i32(163,145,65), Vec3i32(164,180,45), Vec3i32(45,44,164), Vec3i32(44,43,164), Vec3i32(43,42,165), Vec3i32(38,37,151), Vec3i32(150,151,37), Vec3i32(37,93,150), Vec3i32(141,31,30), Vec3i32(30,32,141), Vec3i32(169,168,51), Vec3i32(165,164,43), Vec3i32(189,165,42), Vec3i32(42,41,189), Vec3i32(40,39,152), Vec3i32(40,152,153), Vec3i32(151,152,39), Vec3i32(39,38,151), Vec3i32(93,34,149), Vec3i32(154,189,41), Vec3i32(153,154,41), Vec3i32(41,40,153), Vec3i32(148,149,34), Vec3i32(34,36,148), Vec3i32(36,21,121), Vec3i32(31,174,29), Vec3i32(121,148,36), Vec3i32(21,33,122), Vec3i32(21,122,121), Vec3i32(33,29,122), Vec3i32(174,122,29), Vec3i32(116,188,53), Vec3i32(104,98,10), Vec3i32(87,10,98), Vec3i32(98,100,87), Vec3i32(79,87,100), Vec3i32(79,100,107), Vec3i32(90,79,107), Vec3i32(90,107,178), Vec3i32(178,177,90), Vec3i32(53,90,177), Vec3i32(53,177,117), Vec3i32(117,116,53), Vec3i32(54,53,188), Vec3i32(54,188,187), Vec3i32(67,54,187), Vec3i32(67,187,130), Vec3i32(69,67,130), Vec3i32(69,130,157), Vec3i32(12,69,157), Vec3i32(12,157,136), Vec3i32(136,133,12), Vec3i32(12,133,125), Vec3i32(125,127,12), Vec3i32(13,12,127), Vec3i32(127,146,13), Vec3i32(57,13,146), Vec3i32(57,146,160), Vec3i32(95,57,160), Vec3i32(95,160,173), Vec3i32(173,113,95), Vec3i32(94,95,113), Vec3i32(113,112,94), Vec3i32(52,94,112), Vec3i32(48,52,112), Vec3i32(112,167,48), Vec3i32(35,48,167), Vec3i32(35,167,166), Vec3i32(19,35,166), Vec3i32(139,170,50), Vec3i32(50,49,139), Vec3i32(166,155,19), Vec3i32(20,19,155), Vec3i32(155,124,20), Vec3i32(23,20,124), Vec3i32(23,124,123), Vec3i32(49,23,123), Vec3i32(49,123,142), Vec3i32(142,139,49), Vec3i32(190,191,170), Vec3i32(192,191,190), Vec3i32(191,192,51), Vec3i32(191,51,50), Vec3i32(170,169,190), Vec3i32(169,51,192), Vec3i32(169,192,190), Vec3i32(170,191,50), Vec3i32(193,194,195), Vec3i32(196,197,198), Vec3i32(199,200,201), Vec3i32(198,202,203), Vec3i32(204,201,200), Vec3i32(205,204,200), Vec3i32(206,207,208), Vec3i32(206,208,205), Vec3i32(206,205,200), Vec3i32(207,206,209), Vec3i32(207,209,203), Vec3i32(207,203,202), Vec3i32(202,198,197), Vec3i32(197,196,210), Vec3i32(197,210,195), Vec3i32(197,195,194), Vec3i32(8,88,195), Vec3i32(8,195,210), Vec3i32(210,196,8), Vec3i32(196,198,8), Vec3i32(198,203,8), Vec3i32(203,209,8), Vec3i32(209,206,8), Vec3i32(206,200,8), Vec3i32(202,197,104), Vec3i32(207,202,104), Vec3i32(103,104,197), Vec3i32(103,197,194), Vec3i32(193,195,88), Vec3i32(88,103,194), Vec3i32(88,194,193), Vec3i32(200,199,8), Vec3i32(199,201,8), Vec3i32(204,205,6), Vec3i32(6,8,201), Vec3i32(6,201,204), Vec3i32(10,6,205), Vec3i32(10,205,208), Vec3i32(104,10,208), Vec3i32(104,208,207) }; break; case TestMesh::pyramid: - vertices = std::vector{ - Vec3d(10,10,40), Vec3d(0,0,0), Vec3d(20,0,0), Vec3d(20,20,0), Vec3d(0,20,0) + vertices = std::vector{ + Vec3f(10,10,40), Vec3f(0,0,0), Vec3f(20,0,0), Vec3f(20,20,0), Vec3f(0,20,0) }; facets = std::vector{ Vec3i32(0,1,2), Vec3i32(0,3,4), Vec3i32(3,1,4), Vec3i32(1,3,2), Vec3i32(3,0,2), Vec3i32(4,1,0) }; break; case TestMesh::two_hollow_squares: - vertices = std::vector{ - Vec3d(66.7133483886719,104.286666870117,0), Vec3d(66.7133483886719,95.7133331298828,0), Vec3d(65.6666870117188,94.6666717529297,0), Vec3d(75.2866821289062,95.7133331298828,0), Vec3d(76.3333435058594,105.333335876465,0), Vec3d(76.3333435058594,94.6666717529297,0), - Vec3d(65.6666870117188,105.33332824707,0), Vec3d(75.2866821289062,104.286666870117,0), Vec3d(71.1066818237305,104.58666229248,2.79999995231628), Vec3d(66.4133529663086,104.58666229248,2.79999995231628), Vec3d(75.5866851806641,104.58666229248,2.79999995231628), - Vec3d(66.4133529663086,99.8933334350586,2.79999995231628), Vec3d(66.4133529663086,95.4133377075195,2.79999995231628), Vec3d(71.1066818237305,95.4133377075195,2.79999995231628), Vec3d(75.5866851806641,95.4133377075195,2.79999995231628), Vec3d(75.5866851806641,100.106666564941,2.79999995231628), - Vec3d(74.5400161743164,103.540000915527,2.79999995231628), Vec3d(70.0320129394531,103.540000915527,2.79999995231628), Vec3d(67.4600067138672,103.540000915527,2.79999995231628), Vec3d(67.4600067138672,100.968002319336,2.79999995231628), Vec3d(67.4600067138672,96.4599990844727,2.79999995231628), - Vec3d(74.5400161743164,99.0319976806641,2.79999995231628), Vec3d(74.5400161743164,96.4599990844727,2.79999995231628), Vec3d(70.0320129394531,96.4599990844727,2.79999995231628), Vec3d(123.666717529297,94.6666717529297,0), Vec3d(134.333312988281,94.6666717529297,0), - Vec3d(124.413360595703,95.4133377075195,2.79999995231628), Vec3d(129.106674194336,95.4133377075195,2.79999995231628), Vec3d(133.586669921875,95.4133377075195,2.79999995231628), Vec3d(123.666717529297,105.33332824707,0), Vec3d(124.413360595703,104.58666229248,2.79999995231628), - Vec3d(124.413360595703,99.8933334350586,2.79999995231628), Vec3d(134.333312988281,105.33332824707,0), Vec3d(129.106674194336,104.58666229248,2.79999995231628), Vec3d(133.586669921875,104.58666229248,2.79999995231628), Vec3d(133.586669921875,100.106666564941,2.79999995231628), - Vec3d(124.713317871094,104.286666870117,0), Vec3d(124.713317871094,95.7133331298828,0), Vec3d(133.286712646484,95.7133331298828,0), Vec3d(133.286712646484,104.286666870117,0), Vec3d(132.540023803711,103.540000915527,2.79999995231628), Vec3d(128.032028198242,103.540008544922,2.79999995231628), - Vec3d(125.460006713867,103.540000915527,2.79999995231628), Vec3d(125.460006713867,100.968002319336,2.79999995231628), Vec3d(125.460006713867,96.4599990844727,2.79999995231628), Vec3d(132.540023803711,99.0319976806641,2.79999995231628), Vec3d(132.540023803711,96.4599990844727,2.79999995231628), - Vec3d(128.032028198242,96.4599990844727,2.79999995231628) + vertices = std::vector{ + Vec3f(66.7133483886719,104.286666870117,0), Vec3f(66.7133483886719,95.7133331298828,0), Vec3f(65.6666870117188,94.6666717529297,0), Vec3f(75.2866821289062,95.7133331298828,0), Vec3f(76.3333435058594,105.333335876465,0), Vec3f(76.3333435058594,94.6666717529297,0), + Vec3f(65.6666870117188,105.33332824707,0), Vec3f(75.2866821289062,104.286666870117,0), Vec3f(71.1066818237305,104.58666229248,2.79999995231628), Vec3f(66.4133529663086,104.58666229248,2.79999995231628), Vec3f(75.5866851806641,104.58666229248,2.79999995231628), + Vec3f(66.4133529663086,99.8933334350586,2.79999995231628), Vec3f(66.4133529663086,95.4133377075195,2.79999995231628), Vec3f(71.1066818237305,95.4133377075195,2.79999995231628), Vec3f(75.5866851806641,95.4133377075195,2.79999995231628), Vec3f(75.5866851806641,100.106666564941,2.79999995231628), + Vec3f(74.5400161743164,103.540000915527,2.79999995231628), Vec3f(70.0320129394531,103.540000915527,2.79999995231628), Vec3f(67.4600067138672,103.540000915527,2.79999995231628), Vec3f(67.4600067138672,100.968002319336,2.79999995231628), Vec3f(67.4600067138672,96.4599990844727,2.79999995231628), + Vec3f(74.5400161743164,99.0319976806641,2.79999995231628), Vec3f(74.5400161743164,96.4599990844727,2.79999995231628), Vec3f(70.0320129394531,96.4599990844727,2.79999995231628), Vec3f(123.666717529297,94.6666717529297,0), Vec3f(134.333312988281,94.6666717529297,0), + Vec3f(124.413360595703,95.4133377075195,2.79999995231628), Vec3f(129.106674194336,95.4133377075195,2.79999995231628), Vec3f(133.586669921875,95.4133377075195,2.79999995231628), Vec3f(123.666717529297,105.33332824707,0), Vec3f(124.413360595703,104.58666229248,2.79999995231628), + Vec3f(124.413360595703,99.8933334350586,2.79999995231628), Vec3f(134.333312988281,105.33332824707,0), Vec3f(129.106674194336,104.58666229248,2.79999995231628), Vec3f(133.586669921875,104.58666229248,2.79999995231628), Vec3f(133.586669921875,100.106666564941,2.79999995231628), + Vec3f(124.713317871094,104.286666870117,0), Vec3f(124.713317871094,95.7133331298828,0), Vec3f(133.286712646484,95.7133331298828,0), Vec3f(133.286712646484,104.286666870117,0), Vec3f(132.540023803711,103.540000915527,2.79999995231628), Vec3f(128.032028198242,103.540008544922,2.79999995231628), + Vec3f(125.460006713867,103.540000915527,2.79999995231628), Vec3f(125.460006713867,100.968002319336,2.79999995231628), Vec3f(125.460006713867,96.4599990844727,2.79999995231628), Vec3f(132.540023803711,99.0319976806641,2.79999995231628), Vec3f(132.540023803711,96.4599990844727,2.79999995231628), + Vec3f(128.032028198242,96.4599990844727,2.79999995231628) }; facets = std::vector{ Vec3i32(0,1,2), Vec3i32(3,4,5), Vec3i32(6,4,0), Vec3i32(6,0,2), Vec3i32(2,1,5), Vec3i32(7,4,3), Vec3i32(1,3,5), Vec3i32(0,4,7), Vec3i32(4,6,8), Vec3i32(6,9,8), Vec3i32(4,8,10), Vec3i32(6,2,9), Vec3i32(2,11,9), Vec3i32(2,12,11), Vec3i32(2,5,12), Vec3i32(5,13,12), Vec3i32(5,14,13), @@ -160,17 +160,17 @@ TriangleMesh mesh(TestMesh m) { }; break; case TestMesh::small_dorito: - vertices = std::vector{ - Vec3d(6.00058937072754,-22.9982089996338,0), Vec3d(22.0010242462158,-49.9998741149902,0), Vec3d(-9.99957847595215,-49.999870300293,0), Vec3d(6.00071382522583,-32.2371635437012,28.0019245147705), Vec3d(11.1670551300049,-37.9727020263672,18.9601669311523), - Vec3d(6.00060224533081,-26.5392456054688,10.7321853637695) + vertices = std::vector{ + Vec3f(6.00058937072754,-22.9982089996338,0), Vec3f(22.0010242462158,-49.9998741149902,0), Vec3f(-9.99957847595215,-49.999870300293,0), Vec3f(6.00071382522583,-32.2371635437012,28.0019245147705), Vec3f(11.1670551300049,-37.9727020263672,18.9601669311523), + Vec3f(6.00060224533081,-26.5392456054688,10.7321853637695) }; facets = std::vector{ Vec3i32(0,1,2), Vec3i32(3,4,5), Vec3i32(2,1,4), Vec3i32(2,4,3), Vec3i32(2,3,5), Vec3i32(2,5,0), Vec3i32(5,4,1), Vec3i32(5,1,0) }; break; case TestMesh::bridge: - vertices = std::vector{ - Vec3d(75,84.5,8), Vec3d(125,84.5,8), Vec3d(75,94.5,8), Vec3d(120,84.5,5), Vec3d(125,94.5,8), Vec3d(75,84.5,0), Vec3d(80,84.5,5), Vec3d(125,84.5,0), Vec3d(125,94.5,0), Vec3d(80,94.5,5), Vec3d(75,94.5,0), Vec3d(120,94.5,5), Vec3d(120,84.5,0), Vec3d(80,94.5,0), Vec3d(80,84.5,0), Vec3d(120,94.5,0) + vertices = std::vector{ + Vec3f(75,84.5,8), Vec3f(125,84.5,8), Vec3f(75,94.5,8), Vec3f(120,84.5,5), Vec3f(125,94.5,8), Vec3f(75,84.5,0), Vec3f(80,84.5,5), Vec3f(125,84.5,0), Vec3f(125,94.5,0), Vec3f(80,94.5,5), Vec3f(75,94.5,0), Vec3f(120,94.5,5), Vec3f(120,84.5,0), Vec3f(80,94.5,0), Vec3f(80,84.5,0), Vec3f(120,94.5,0) }; facets = std::vector{ Vec3i32(0,1,2), Vec3i32(1,0,3), Vec3i32(2,1,4), Vec3i32(2,5,0), Vec3i32(0,6,3), Vec3i32(1,3,7), Vec3i32(1,8,4), Vec3i32(4,9,2), Vec3i32(10,5,2), Vec3i32(5,6,0), Vec3i32(6,11,3), Vec3i32(3,12,7), Vec3i32(7,8,1), Vec3i32(4,8,11), Vec3i32(4,11,9), Vec3i32(9,10,2), Vec3i32(10,13,5), @@ -178,8 +178,8 @@ TriangleMesh mesh(TestMesh m) { }; break; case TestMesh::bridge_with_hole: - vertices = std::vector{ - Vec3d(75,69.5,8), Vec3d(80,76.9091644287109,8), Vec3d(75,94.5,8), Vec3d(125,69.5,8), Vec3d(120,76.9091644287109,8), Vec3d(120,87.0908355712891,8), Vec3d(80,87.0908355712891,8), Vec3d(125,94.5,8), Vec3d(80,87.0908355712891,5), Vec3d(120,87.0908355712891,5), Vec3d(125,94.5,0), Vec3d(120,69.5,0), Vec3d(120,94.5,0), Vec3d(125,69.5,0), Vec3d(120,94.5,5), Vec3d(80,94.5,5), Vec3d(80,94.5,0), Vec3d(75,94.5,0), Vec3d(80,69.5,5), Vec3d(80,69.5,0), Vec3d(80,76.9091644287109,5), Vec3d(120,69.5,5), Vec3d(75,69.5,0), Vec3d(120,76.9091644287109,5) + vertices = std::vector{ + Vec3f(75,69.5,8), Vec3f(80,76.9091644287109,8), Vec3f(75,94.5,8), Vec3f(125,69.5,8), Vec3f(120,76.9091644287109,8), Vec3f(120,87.0908355712891,8), Vec3f(80,87.0908355712891,8), Vec3f(125,94.5,8), Vec3f(80,87.0908355712891,5), Vec3f(120,87.0908355712891,5), Vec3f(125,94.5,0), Vec3f(120,69.5,0), Vec3f(120,94.5,0), Vec3f(125,69.5,0), Vec3f(120,94.5,5), Vec3f(80,94.5,5), Vec3f(80,94.5,0), Vec3f(75,94.5,0), Vec3f(80,69.5,5), Vec3f(80,69.5,0), Vec3f(80,76.9091644287109,5), Vec3f(120,69.5,5), Vec3f(75,69.5,0), Vec3f(120,76.9091644287109,5) }; facets = std::vector{ Vec3i32(0,1,2), Vec3i32(1,0,3), Vec3i32(1,3,4), Vec3i32(4,3,5), Vec3i32(2,6,7), Vec3i32(6,2,1), Vec3i32(7,6,5), Vec3i32(7,5,3), Vec3i32(5,8,9), Vec3i32(8,5,6), Vec3i32(10,11,12), Vec3i32(11,10,13), Vec3i32(14,8,15), Vec3i32(8,14,9), Vec3i32(2,16,17), Vec3i32(16,2,15), Vec3i32(15,2,14), @@ -187,8 +187,8 @@ TriangleMesh mesh(TestMesh m) { }; break; case TestMesh::step: - vertices = std::vector{ - Vec3d(0,20,5), Vec3d(0,20,0), Vec3d(0,0,5), Vec3d(0,0,0), Vec3d(20,0,0), Vec3d(20,0,5), Vec3d(1,19,5), Vec3d(1,1,5), Vec3d(19,1,5), Vec3d(20,20,5), Vec3d(19,19,5), Vec3d(20,20,0), Vec3d(19,19,10), Vec3d(1,19,10), Vec3d(1,1,10), Vec3d(19,1,10) + vertices = std::vector{ + Vec3f(0,20,5), Vec3f(0,20,0), Vec3f(0,0,5), Vec3f(0,0,0), Vec3f(20,0,0), Vec3f(20,0,5), Vec3f(1,19,5), Vec3f(1,1,5), Vec3f(19,1,5), Vec3f(20,20,5), Vec3f(19,19,5), Vec3f(20,20,0), Vec3f(19,19,10), Vec3f(1,19,10), Vec3f(1,1,10), Vec3f(19,1,10) }; facets = std::vector{ Vec3i32(0,1,2), Vec3i32(1,3,2), Vec3i32(3,4,5), Vec3i32(2,3,5), Vec3i32(6,0,2), Vec3i32(6,2,7), Vec3i32(5,8,7), Vec3i32(5,7,2), Vec3i32(9,10,8), Vec3i32(9,8,5), Vec3i32(9,0,6), Vec3i32(9,6,10), Vec3i32(9,11,1), Vec3i32(9,1,0), Vec3i32(3,1,11), Vec3i32(4,3,11), Vec3i32(5,11,9), @@ -196,9 +196,9 @@ TriangleMesh mesh(TestMesh m) { }; break; case TestMesh::slopy_cube: - vertices = std::vector{ - Vec3d(-10,-10,0) , Vec3d(-10,-10,20) , Vec3d(-10,10,0) , Vec3d(-10,10,20) , Vec3d(0,-10,10) , Vec3d(10,-10,0) , Vec3d(2.92893,-10,10) , Vec3d(10,-10,2.92893) , - Vec3d(0,-10,20) , Vec3d(10,10,0) , Vec3d(0,10,10) , Vec3d(0,10,20) , Vec3d(2.92893,10,10) , Vec3d(10,10,2.92893) + vertices = std::vector{ + Vec3f(-10,-10,0) , Vec3f(-10,-10,20) , Vec3f(-10,10,0) , Vec3f(-10,10,20) , Vec3f(0,-10,10) , Vec3f(10,-10,0) , Vec3f(2.92893,-10,10) , Vec3f(10,-10,2.92893) , + Vec3f(0,-10,20) , Vec3f(10,10,0) , Vec3f(0,10,10) , Vec3f(0,10,20) , Vec3f(2.92893,10,10) , Vec3f(10,10,2.92893) }; facets = std::vector{ Vec3i32(0,1,2) , Vec3i32(2,1,3) , Vec3i32(4,0,5) , Vec3i32(4,1,0) , Vec3i32(6,4,7) , Vec3i32(7,4,5) , Vec3i32(4,8,1) , Vec3i32(0,2,5) , Vec3i32(5,2,9) , Vec3i32(2,10,9) , Vec3i32(10,3,11) , @@ -207,8 +207,8 @@ TriangleMesh mesh(TestMesh m) { }; break; case TestMesh::di_5mm_center_notch: - vertices = std::vector{ - Vec3d(-15,-15,0),Vec3d(-15,15,10),Vec3d(-15,15,0),Vec3d(-15,-15,10),Vec3d(3,-2,10),Vec3d(15,15,10),Vec3d(3,3,10),Vec3d(-2,3,10),Vec3d(-2,-2,10),Vec3d(15,-15,10),Vec3d(15,15,0),Vec3d(15,-15,0),Vec3d(-2,3,5),Vec3d(-2,-2,5),Vec3d(3,-2,5),Vec3d(3,3,5) + vertices = std::vector{ + Vec3f(-15,-15,0),Vec3f(-15,15,10),Vec3f(-15,15,0),Vec3f(-15,-15,10),Vec3f(3,-2,10),Vec3f(15,15,10),Vec3f(3,3,10),Vec3f(-2,3,10),Vec3f(-2,-2,10),Vec3f(15,-15,10),Vec3f(15,15,0),Vec3f(15,-15,0),Vec3f(-2,3,5),Vec3f(-2,-2,5),Vec3f(3,-2,5),Vec3f(3,3,5) }; facets = std::vector{ Vec3i32(0,1,2),Vec3i32(1,0,3),Vec3i32(4,5,6),Vec3i32(5,7,6),Vec3i32(7,1,8),Vec3i32(1,7,5),Vec3i32(5,4,9),Vec3i32(8,9,4),Vec3i32(8,3,9),Vec3i32(3,8,1),Vec3i32(9,10,5),Vec3i32(10,9,11),Vec3i32(10,1,5),Vec3i32(1,10,2),Vec3i32(0,10,11),Vec3i32(10,0,2),Vec3i32(0,9,3),Vec3i32(9,0,11), @@ -216,8 +216,8 @@ TriangleMesh mesh(TestMesh m) { }; break; case TestMesh::di_10mm_notch: - vertices = std::vector{ - Vec3d(-15,15,0),Vec3d(-15,-5,5),Vec3d(-15,15,10),Vec3d(-15,-15,0),Vec3d(-15,-15,5),Vec3d(-15,-5,10),Vec3d(15,15,10),Vec3d(-5,-5,10),Vec3d(15,-15,10),Vec3d(-5,-15,10),Vec3d(15,15,0),Vec3d(15,-15,0),Vec3d(-5,-15,5),Vec3d(-5,-5,5) + vertices = std::vector{ + Vec3f(-15,15,0),Vec3f(-15,-5,5),Vec3f(-15,15,10),Vec3f(-15,-15,0),Vec3f(-15,-15,5),Vec3f(-15,-5,10),Vec3f(15,15,10),Vec3f(-5,-5,10),Vec3f(15,-15,10),Vec3f(-5,-15,10),Vec3f(15,15,0),Vec3f(15,-15,0),Vec3f(-5,-15,5),Vec3f(-5,-5,5) }; facets = std::vector{ Vec3i32(0,1,2),Vec3i32(3,1,0),Vec3i32(1,3,4),Vec3i32(2,1,5),Vec3i32(6,7,8),Vec3i32(2,7,6),Vec3i32(7,2,5),Vec3i32(8,7,9),Vec3i32(8,10,6),Vec3i32(10,8,11),Vec3i32(10,2,6),Vec3i32(2,10,0),Vec3i32(3,10,11),Vec3i32(10,3,0),Vec3i32(4,3,12),Vec3i32(12,8,9),Vec3i32(11,12,3),Vec3i32(12,11,8), @@ -225,8 +225,8 @@ TriangleMesh mesh(TestMesh m) { }; break; case TestMesh::di_20mm_notch: - vertices = std::vector{ - Vec3d(-15,15,0),Vec3d(-15,5,5),Vec3d(-15,15,10),Vec3d(-15,-15,0),Vec3d(-15,-15,5),Vec3d(-15,5,10),Vec3d(15,15,10),Vec3d(5,5,10),Vec3d(15,-15,10),Vec3d(5,-15,10),Vec3d(15,15,0),Vec3d(15,-15,0),Vec3d(5,-15,5),Vec3d(5,5,5) + vertices = std::vector{ + Vec3f(-15,15,0),Vec3f(-15,5,5),Vec3f(-15,15,10),Vec3f(-15,-15,0),Vec3f(-15,-15,5),Vec3f(-15,5,10),Vec3f(15,15,10),Vec3f(5,5,10),Vec3f(15,-15,10),Vec3f(5,-15,10),Vec3f(15,15,0),Vec3f(15,-15,0),Vec3f(5,-15,5),Vec3f(5,5,5) }; facets = std::vector{ Vec3i32(0,1,2),Vec3i32(3,1,0),Vec3i32(1,3,4),Vec3i32(2,1,5),Vec3i32(6,7,8),Vec3i32(2,7,6),Vec3i32(7,2,5),Vec3i32(8,7,9),Vec3i32(8,10,6),Vec3i32(10,8,11),Vec3i32(3,10,11),Vec3i32(10,3,0),Vec3i32(4,3,12),Vec3i32(12,8,9),Vec3i32(12,11,8),Vec3i32(11,12,3),Vec3i32(10,2,6),Vec3i32(2,10,0), @@ -234,8 +234,8 @@ TriangleMesh mesh(TestMesh m) { }; break; case TestMesh::di_25mm_notch: - vertices = std::vector{ - Vec3d(-15,15,0),Vec3d(-15,10,5),Vec3d(-15,15,10),Vec3d(-15,-15,0),Vec3d(-15,-15,5),Vec3d(-15,10,10),Vec3d(15,15,10),Vec3d(10,10,10),Vec3d(15,-15,10),Vec3d(10,-15,10),Vec3d(15,15,0),Vec3d(15,-15,0),Vec3d(10,-15,5),Vec3d(10,10,5) + vertices = std::vector{ + Vec3f(-15,15,0),Vec3f(-15,10,5),Vec3f(-15,15,10),Vec3f(-15,-15,0),Vec3f(-15,-15,5),Vec3f(-15,10,10),Vec3f(15,15,10),Vec3f(10,10,10),Vec3f(15,-15,10),Vec3f(10,-15,10),Vec3f(15,15,0),Vec3f(15,-15,0),Vec3f(10,-15,5),Vec3f(10,10,5) }; facets = std::vector{ Vec3i32(0,1,2),Vec3i32(3,1,0),Vec3i32(1,3,4),Vec3i32(2,1,5),Vec3i32(6,7,8),Vec3i32(2,7,6),Vec3i32(7,2,5),Vec3i32(8,7,9),Vec3i32(8,10,6),Vec3i32(10,8,11),Vec3i32(3,10,11),Vec3i32(10,3,0),Vec3i32(4,3,12),Vec3i32(12,8,9),Vec3i32(12,11,8),Vec3i32(11,12,3),Vec3i32(10,2,6),Vec3i32(2,10,0), @@ -261,7 +261,7 @@ TriangleMesh mesh(TestMesh m) { _mesh = TriangleMesh(vertices, facets); } - _mesh.repair(); + //_mesh.repair(); return _mesh; } @@ -269,7 +269,9 @@ TriangleMesh mesh(TestMesh m) { void init_print(Print& print, std::initializer_list meshes, Slic3r::Model& model, DynamicPrintConfig* _config, bool comments) { DynamicPrintConfig &config = Slic3r::DynamicPrintConfig::full_print_config(); config.apply(*_config); - + + //remove print of status + print.set_status_callback([](const PrintBase::SlicingStatus &) {}); //const std::string v {std::getenv("SLIC3R_TESTS_GCODE")}; //auto tests_gcode {(v == "" ? ""s : std::string(v))}; @@ -288,7 +290,7 @@ void init_print(Print& print, std::initializer_list meshes, Slic3r::Mo } print.apply(model, config); // apply config for the arrange_objects - arrange_objects(model, InfiniteBed{}, ArrangeParams{ scaled(print.config().min_object_distance()) }); + arrange_objects(model, InfiniteBed{}, ArrangeParams{ scale_t(10)});//print.config().min_object_distance()) }); model.center_instances_around_point(Slic3r::Vec2d(100,100)); for (auto* mo : model.objects) { print.auto_assign_extruders(mo); @@ -304,7 +306,9 @@ void init_print(Print& print, std::initializer_list meshes, Slic3r::Mo void init_print(Print& print, std::vector meshes, Slic3r::Model& model, DynamicPrintConfig* _config, bool comments) { DynamicPrintConfig &config = Slic3r::DynamicPrintConfig::full_print_config(); config.apply(*_config); - + + //remove print of status + print.set_status_callback([](const PrintBase::SlicingStatus &) {}); //const std::string v {std::getenv("SLIC3R_TESTS_GCODE")}; //std::string tests_gcode {(v == "" ? "" : v)}; @@ -312,8 +316,8 @@ void init_print(Print& print, std::vector meshes, Slic3r::Model& m //config->set_key_value("gcode_comments", new ConfigOptionBool(true)); for (TriangleMesh& t : meshes) { - if(!t.repaired) - t.repair(); + //if(!t.repaired()) + //t.repair(); ModelObject* object {model.add_object()}; object->name += "object.stl"s; object->add_volume(t); @@ -324,7 +328,7 @@ void init_print(Print& print, std::vector meshes, Slic3r::Model& m } print.apply(model, config); // apply config for the arrange_objects - arrange_objects(model, InfiniteBed{}, ArrangeParams{ scaled(print.config().min_object_distance()) }); + arrange_objects(model, InfiniteBed{}, ArrangeParams{scale_t(10)} );//print.config().min_object_distance())}); model.center_instances_around_point(Slic3r::Vec2d(100,100)); print.apply(model, config); for (ModelObject* mo : model.objects) { diff --git a/tests/superslicerlibslic3r/test_dense_infill.cpp b/tests/superslicerlibslic3r/test_dense_infill.cpp index 060483cecb1..a57f77b3fca 100644 --- a/tests/superslicerlibslic3r/test_dense_infill.cpp +++ b/tests/superslicerlibslic3r/test_dense_infill.cpp @@ -2,7 +2,6 @@ //#define CATCH_CONFIG_DISABLE //#include #include -//#include #include #include "test_data.hpp" @@ -33,18 +32,17 @@ SCENARIO("test auto generation") { //config.set_deserialize("infill_dense_algo", "50"); //config.set_deserialize("extruder_clearance_radius", "10"); WHEN("little surface") { - ExPolygon polygon_to_cover; - polygon_to_cover.contour = get_polygon_scale({ {0,0}, {10,0}, {10,10}, {0,10} }); + ExPolygon expolygon_to_cover; + expolygon_to_cover.contour = get_polygon_scale({ {0,0}, {10,0}, {10,10}, {0,10} }); ExPolygon growing_area; growing_area.contour = get_polygon_scale({ {0,0}, {40,0}, {0,40} }); - ExPolygons allowedPoints; - allowedPoints.emplace_back(); - //diff_ex(offset_ex(growing_area, scale_(1)), offset_ex(layerm->fill_no_overlap_expolygons, double(-layerm->flow(frInfill).scaled_width()))); - allowedPoints.back().contour = get_polygon_scale({ {0,0}, {40,0}, {0,40} }); + //ExPolygons allowedPoints; + //allowedPoints.emplace_back(); + //allowedPoints.back().contour = get_polygon_scale({ {0,0}, {40,0}, {0,40} }); coord_t offset = scale_(2); float coverage = 1.f; - ExPolygons solution = dense_fill_fit_to_size(polygon_to_cover, allowedPoints, growing_area, offset, coverage); + ExPolygons solution = dense_fill_fit_to_size(expolygon_to_cover, growing_area, offset, coverage); THEN("little support") { double area_result = 0; for (ExPolygon& p : solution) diff --git a/tests/superslicerlibslic3r/test_denserinfill.cpp b/tests/superslicerlibslic3r/test_denserinfill.cpp index 2b09c8df727..961c5feb4ab 100644 --- a/tests/superslicerlibslic3r/test_denserinfill.cpp +++ b/tests/superslicerlibslic3r/test_denserinfill.cpp @@ -1,9 +1,10 @@ //#define CATCH_CONFIG_DISABLE - -#include +#include #include "test_data.hpp" #include +#include +#include using namespace Slic3r; using namespace Slic3r::Geometry; @@ -26,14 +27,14 @@ SCENARIO("denser infills: ") config.save("C:\\Users\\Admin\\Desktop\\config_def.ini"); Slic3r::Test::init_print(print, { Slic3r::Test::TestMesh::di_5mm_center_notch }, model, &config, false); print.process(); - PrintObject& object = *(print.objects().at(0)); + const PrintObject& object = *(print.objects().at(0)); //for (int lidx = 0; lidx < object.layers().size(); lidx++) { // std::cout << "layer " << lidx << " : \n"; // std::cout << " - region_count= " << object.layers()[lidx]->region_count() << "\n"; // for (int ridx = 0; ridx < object.layers()[lidx]->regions().size(); ridx++) { // std::cout << " region " << ridx << " : \n"; - // std::cout << " - fills= " << object.layers()[lidx]->regions()[ridx]->fills.entities.size() << "\n"; + // std::cout << " - fills= " << object.layers()[lidx]->regions()[ridx]->fills.entities().size() << "\n"; // std::cout << " - surfaces= " << object.layers()[lidx]->regions()[ridx]->fill_surfaces.surfaces.size() << "\n"; // for (int sidx = 0; sidx < object.layers()[lidx]->regions()[ridx]->fill_surfaces.surfaces.size(); sidx++) { // std::cout << " - type= " << object.layers()[lidx]->regions()[ridx]->fill_surfaces.surfaces[sidx].surface_type << "\n"; @@ -53,8 +54,8 @@ SCENARIO("denser infills: ") REQUIRE(object.layers()[18]->region_count() == 2); }*/ THEN("correct number of fills") { - REQUIRE(object.layers()[20]->regions()[0]->fills.entities.size() == 1); //sparse - REQUIRE(object.layers()[21]->regions()[0]->fills.entities.size() == 2); //sparse + dense + REQUIRE(object.layers()[20]->regions()[0]->fills.entities().size() == 1); //sparse + REQUIRE(object.layers()[21]->regions()[0]->fills.entities().size() == 2); //sparse + dense REQUIRE(object.layers()[21]->regions()[0]->fill_surfaces.surfaces.size() == 2); REQUIRE(object.layers()[21]->regions()[0]->fill_surfaces.surfaces[0].surface_type == (SurfaceType::stDensSparse | SurfaceType::stPosInternal)); REQUIRE(object.layers()[21]->regions()[0]->fill_surfaces.surfaces[1].surface_type == (SurfaceType::stDensSparse | SurfaceType::stPosInternal)); @@ -67,7 +68,7 @@ SCENARIO("denser infills: ") } //std::cout << "sparse area = " << unscaled(unscaled(srfSparse->area())) << " , dense area = " << unscaled(unscaled(srfDense->area())) << "\n"; REQUIRE(unscaled(unscaled(srfSparse->area())) > unscaled(unscaled(srfDense->area()))); - REQUIRE(object.layers()[22]->regions()[0]->fills.entities.size() == 2); //sparse + solid-bridge + REQUIRE(object.layers()[22]->regions()[0]->fills.entities().size() == 2); //sparse + solid-bridge REQUIRE(object.layers()[22]->regions()[0]->fill_surfaces.surfaces.size() == 2); if (object.layers()[22]->regions()[0]->fill_surfaces.surfaces[0].surface_type == (SurfaceType::stDensSparse | SurfaceType::stPosInternal)) { REQUIRE(object.layers()[22]->regions()[0]->fill_surfaces.surfaces[1].surface_type == (SurfaceType::stDensSolid | SurfaceType::stPosInternal | SurfaceType::stModBridge)); @@ -75,9 +76,9 @@ SCENARIO("denser infills: ") REQUIRE(object.layers()[22]->regions()[0]->fill_surfaces.surfaces[0].surface_type == (SurfaceType::stDensSolid | SurfaceType::stPosInternal | SurfaceType::stModBridge)); REQUIRE(object.layers()[22]->regions()[0]->fill_surfaces.surfaces[1].surface_type == (SurfaceType::stDensSparse | SurfaceType::stPosInternal)); } - REQUIRE(object.layers()[23]->regions()[0]->fills.entities.size() == 2); //sparse + solid - REQUIRE(object.layers()[24]->regions()[0]->fills.entities.size() == 3); //sparse + solid-top + solid-top (over perimeters) - REQUIRE(object.layers()[25]->regions()[0]->fills.entities.size() == 1); //sparse + REQUIRE(object.layers()[23]->regions()[0]->fills.entities().size() == 2); //sparse + solid + REQUIRE(object.layers()[24]->regions()[0]->fills.entities().size() == 3); //sparse + solid-top + solid-top (over perimeters) + REQUIRE(object.layers()[25]->regions()[0]->fills.entities().size() == 1); //sparse } } } @@ -95,11 +96,11 @@ SCENARIO("denser infills: ") config.save("C:\\Users\\Admin\\Desktop\\config_def.ini"); Slic3r::Test::init_print(print, { Slic3r::Test::TestMesh::di_10mm_notch }, model, &config, false); print.process(); - PrintObject& object = *(print.objects().at(0)); + const PrintObject& object = *(print.objects().at(0)); THEN("correct number of fills") { REQUIRE(object.layers().size() == 50); - REQUIRE(object.layers()[20]->regions()[0]->fills.entities.size() == 1); //sparse - REQUIRE(object.layers()[21]->regions()[0]->fills.entities.size() == 2); //sparse + dense + REQUIRE(object.layers()[20]->regions()[0]->fills.entities().size() == 1); //sparse + REQUIRE(object.layers()[21]->regions()[0]->fills.entities().size() == 2); //sparse + dense REQUIRE(object.layers()[21]->regions()[0]->fill_surfaces.surfaces.size() == 2); REQUIRE(object.layers()[21]->regions()[0]->fill_surfaces.surfaces[0].surface_type == (SurfaceType::stDensSparse | SurfaceType::stPosInternal)); REQUIRE(object.layers()[21]->regions()[0]->fill_surfaces.surfaces[1].surface_type == (SurfaceType::stDensSparse | SurfaceType::stPosInternal)); @@ -111,7 +112,7 @@ SCENARIO("denser infills: ") srfDense = &object.layers()[21]->regions()[0]->fill_surfaces.surfaces[0]; } REQUIRE(unscaled(unscaled(srfSparse->area())) > unscaled(unscaled(srfDense->area()))); - REQUIRE(object.layers()[22]->regions()[0]->fills.entities.size() == 2); //sparse + solid-bridge + REQUIRE(object.layers()[22]->regions()[0]->fills.entities().size() == 2); //sparse + solid-bridge REQUIRE(object.layers()[22]->regions()[0]->fill_surfaces.surfaces.size() == 2); if (object.layers()[22]->regions()[0]->fill_surfaces.surfaces[0].surface_type == (SurfaceType::stDensSparse | SurfaceType::stPosInternal)) { REQUIRE(object.layers()[22]->regions()[0]->fill_surfaces.surfaces[1].surface_type == (SurfaceType::stDensSolid | SurfaceType::stPosInternal | SurfaceType::stModBridge)); @@ -119,27 +120,27 @@ SCENARIO("denser infills: ") REQUIRE(object.layers()[22]->regions()[0]->fill_surfaces.surfaces[0].surface_type == (SurfaceType::stDensSolid | SurfaceType::stPosInternal | SurfaceType::stModBridge)); REQUIRE(object.layers()[22]->regions()[0]->fill_surfaces.surfaces[1].surface_type == (SurfaceType::stDensSparse | SurfaceType::stPosInternal)); } - REQUIRE(object.layers()[23]->regions()[0]->fills.entities.size() == 2); //sparse + solid - REQUIRE(object.layers()[24]->regions()[0]->fills.entities.size() == 3); //sparse + solid-top + solid-top (over perimeters) - REQUIRE(object.layers()[25]->regions()[0]->fills.entities.size() == 1); //sparse - REQUIRE(object.layers()[45]->regions()[0]->fills.entities.size() == 1); //sparse + REQUIRE(object.layers()[23]->regions()[0]->fills.entities().size() == 2); //sparse + solid + REQUIRE(object.layers()[24]->regions()[0]->fills.entities().size() == 3); //sparse + solid-top + solid-top (over perimeters) + REQUIRE(object.layers()[25]->regions()[0]->fills.entities().size() == 1); //sparse + REQUIRE(object.layers()[45]->regions()[0]->fills.entities().size() == 1); //sparse REQUIRE(object.layers()[45]->regions()[0]->fill_surfaces.surfaces.size() == 1); REQUIRE(object.layers()[45]->regions()[0]->fill_surfaces.surfaces[0].surface_type == (SurfaceType::stDensSparse | SurfaceType::stPosInternal)); REQUIRE(object.layers()[45]->regions()[0]->fill_surfaces.surfaces[0].maxNbSolidLayersOnTop > 1); - REQUIRE(object.layers()[46]->regions()[0]->fills.entities.size() == 1); //dense - REQUIRE(object.layers()[46]->regions()[0]->fills.entities.size() == 1); + REQUIRE(object.layers()[46]->regions()[0]->fills.entities().size() == 1); //dense + REQUIRE(object.layers()[46]->regions()[0]->fills.entities().size() == 1); REQUIRE(object.layers()[46]->regions()[0]->fill_surfaces.surfaces.size() == 1); REQUIRE(object.layers()[46]->regions()[0]->fill_surfaces.surfaces[0].surface_type == (SurfaceType::stDensSparse | SurfaceType::stPosInternal)); REQUIRE(object.layers()[46]->regions()[0]->fill_surfaces.surfaces[0].maxNbSolidLayersOnTop == 1); - REQUIRE(object.layers()[47]->regions()[0]->fills.entities.size() == 1); //solid-bridge + REQUIRE(object.layers()[47]->regions()[0]->fills.entities().size() == 1); //solid-bridge REQUIRE(object.layers()[47]->regions()[0]->fill_surfaces.surfaces.size() == 1); REQUIRE(object.layers()[47]->regions()[0]->fill_surfaces.surfaces[0].surface_type == (SurfaceType::stDensSolid | SurfaceType::stPosInternal | SurfaceType::stModBridge)); REQUIRE(object.layers()[47]->regions()[0]->fill_surfaces.surfaces[0].maxNbSolidLayersOnTop > 1); - REQUIRE(object.layers()[48]->regions()[0]->fills.entities.size() == 1); //solid + REQUIRE(object.layers()[48]->regions()[0]->fills.entities().size() == 1); //solid REQUIRE(object.layers()[48]->regions()[0]->fill_surfaces.surfaces.size() == 1); REQUIRE(object.layers()[48]->regions()[0]->fill_surfaces.surfaces[0].surface_type == (SurfaceType::stDensSolid | SurfaceType::stPosInternal)); REQUIRE(object.layers()[48]->regions()[0]->fill_surfaces.surfaces[0].maxNbSolidLayersOnTop > 1); - REQUIRE(object.layers()[49]->regions()[0]->fills.entities.size() == 1); //top + REQUIRE(object.layers()[49]->regions()[0]->fills.entities().size() == 1); //top REQUIRE(object.layers()[49]->regions()[0]->fill_surfaces.surfaces.size() == 1); REQUIRE(object.layers()[49]->regions()[0]->fill_surfaces.surfaces[0].surface_type == (SurfaceType::stDensSolid | SurfaceType::stPosTop)); REQUIRE(object.layers()[49]->regions()[0]->fill_surfaces.surfaces[0].maxNbSolidLayersOnTop > 1); @@ -157,11 +158,11 @@ SCENARIO("denser infills: ") config.save("C:\\Users\\Admin\\Desktop\\config_def.ini"); Slic3r::Test::init_print(print, { Slic3r::Test::TestMesh::di_10mm_notch }, model, &config, false); print.process(); - PrintObject& object = *(print.objects().at(0)); + const PrintObject& object = *(print.objects().at(0)); THEN("correct number of fills") { REQUIRE(object.layers().size() == 50); - REQUIRE(object.layers()[20]->regions()[0]->fills.entities.size() == 1); //sparse - REQUIRE(object.layers()[21]->regions()[0]->fills.entities.size() == 2); //sparse + dense + REQUIRE(object.layers()[20]->regions()[0]->fills.entities().size() == 1); //sparse + REQUIRE(object.layers()[21]->regions()[0]->fills.entities().size() == 2); //sparse + dense REQUIRE(object.layers()[21]->regions()[0]->fill_surfaces.surfaces.size() == 2); REQUIRE(object.layers()[21]->regions()[0]->fill_surfaces.surfaces[0].surface_type == (SurfaceType::stDensSparse | SurfaceType::stPosInternal)); REQUIRE(object.layers()[21]->regions()[0]->fill_surfaces.surfaces[1].surface_type == (SurfaceType::stDensSparse | SurfaceType::stPosInternal)); @@ -173,7 +174,7 @@ SCENARIO("denser infills: ") srfDense = &object.layers()[21]->regions()[0]->fill_surfaces.surfaces[0]; } REQUIRE(unscaled(unscaled(srfSparse->area())) > unscaled(unscaled(srfDense->area()))); - REQUIRE(object.layers()[22]->regions()[0]->fills.entities.size() == 2); //sparse + solid-bridge + REQUIRE(object.layers()[22]->regions()[0]->fills.entities().size() == 2); //sparse + solid-bridge REQUIRE(object.layers()[22]->regions()[0]->fill_surfaces.surfaces.size() == 2); if (object.layers()[22]->regions()[0]->fill_surfaces.surfaces[0].surface_type == (SurfaceType::stDensSparse | SurfaceType::stPosInternal)) { REQUIRE(object.layers()[22]->regions()[0]->fill_surfaces.surfaces[1].surface_type == (SurfaceType::stDensSolid | SurfaceType::stPosInternal | SurfaceType::stModBridge)); @@ -181,26 +182,26 @@ SCENARIO("denser infills: ") REQUIRE(object.layers()[22]->regions()[0]->fill_surfaces.surfaces[0].surface_type == (SurfaceType::stDensSolid | SurfaceType::stPosInternal | SurfaceType::stModBridge)); REQUIRE(object.layers()[22]->regions()[0]->fill_surfaces.surfaces[1].surface_type == (SurfaceType::stDensSparse | SurfaceType::stPosInternal)); } - REQUIRE(object.layers()[23]->regions()[0]->fills.entities.size() == 2); //sparse + solid - REQUIRE(object.layers()[24]->regions()[0]->fills.entities.size() == 3); //sparse + solid-top + solid-top (over perimeters) - REQUIRE(object.layers()[25]->regions()[0]->fills.entities.size() == 1); //sparse - REQUIRE(object.layers()[45]->regions()[0]->fills.entities.size() == 1); //sparse + REQUIRE(object.layers()[23]->regions()[0]->fills.entities().size() == 2); //sparse + solid + REQUIRE(object.layers()[24]->regions()[0]->fills.entities().size() == 3); //sparse + solid-top + solid-top (over perimeters) + REQUIRE(object.layers()[25]->regions()[0]->fills.entities().size() == 1); //sparse + REQUIRE(object.layers()[45]->regions()[0]->fills.entities().size() == 1); //sparse REQUIRE(object.layers()[45]->regions()[0]->fill_surfaces.surfaces.size() == 1); REQUIRE(object.layers()[45]->regions()[0]->fill_surfaces.surfaces[0].surface_type == (SurfaceType::stDensSparse | SurfaceType::stPosInternal)); REQUIRE(object.layers()[45]->regions()[0]->fill_surfaces.surfaces[0].maxNbSolidLayersOnTop > 1); - REQUIRE(object.layers()[46]->regions()[0]->fills.entities.size() == 1); //dense + REQUIRE(object.layers()[46]->regions()[0]->fills.entities().size() == 1); //dense REQUIRE(object.layers()[46]->regions()[0]->fill_surfaces.surfaces.size() == 1); REQUIRE(object.layers()[46]->regions()[0]->fill_surfaces.surfaces[0].surface_type == (SurfaceType::stDensSparse | SurfaceType::stPosInternal)); REQUIRE(object.layers()[46]->regions()[0]->fill_surfaces.surfaces[0].maxNbSolidLayersOnTop > 1); - REQUIRE(object.layers()[47]->regions()[0]->fills.entities.size() == 1); //solid-bridge + REQUIRE(object.layers()[47]->regions()[0]->fills.entities().size() == 1); //solid-bridge REQUIRE(object.layers()[47]->regions()[0]->fill_surfaces.surfaces.size() == 1); REQUIRE(object.layers()[47]->regions()[0]->fill_surfaces.surfaces[0].surface_type == (SurfaceType::stDensSolid | SurfaceType::stPosInternal | SurfaceType::stModBridge)); REQUIRE(object.layers()[47]->regions()[0]->fill_surfaces.surfaces[0].maxNbSolidLayersOnTop > 1); - REQUIRE(object.layers()[48]->regions()[0]->fills.entities.size() == 1); //solid + REQUIRE(object.layers()[48]->regions()[0]->fills.entities().size() == 1); //solid REQUIRE(object.layers()[48]->regions()[0]->fill_surfaces.surfaces.size() == 1); REQUIRE(object.layers()[48]->regions()[0]->fill_surfaces.surfaces[0].surface_type == (SurfaceType::stDensSolid | SurfaceType::stPosInternal)); REQUIRE(object.layers()[48]->regions()[0]->fill_surfaces.surfaces[0].maxNbSolidLayersOnTop > 1); - REQUIRE(object.layers()[49]->regions()[0]->fills.entities.size() == 1); //top + REQUIRE(object.layers()[49]->regions()[0]->fills.entities().size() == 1); //top REQUIRE(object.layers()[49]->regions()[0]->fill_surfaces.surfaces.size() == 1); REQUIRE(object.layers()[49]->regions()[0]->fill_surfaces.surfaces[0].surface_type == (SurfaceType::stDensSolid | SurfaceType::stPosTop)); REQUIRE(object.layers()[49]->regions()[0]->fill_surfaces.surfaces[0].maxNbSolidLayersOnTop > 1); diff --git a/tests/superslicerlibslic3r/test_extrusion_entity.cpp b/tests/superslicerlibslic3r/test_extrusion_entity.cpp index a4d308a99a5..88a1fc01c5e 100644 --- a/tests/superslicerlibslic3r/test_extrusion_entity.cpp +++ b/tests/superslicerlibslic3r/test_extrusion_entity.cpp @@ -1,13 +1,15 @@ //#define CATCH_CONFIG_DISABLE -#include +#include #include #include "test_data.hpp" #include #include #include #include +#include +#include #include #include @@ -21,7 +23,7 @@ Slic3r::Point random_point(float LO=-50, float HI=50) { // build a sample extrusion entity collection with random start and end points. Slic3r::ExtrusionPath random_path(size_t length = 20, float LO=-50, float HI=50) { - Slic3r::ExtrusionPath t { Slic3r::ExtrusionRole::erPerimeter, 1.0, 1.0, 1.0}; + Slic3r::ExtrusionPath t(Slic3r::ExtrusionRole::erPerimeter, 1.0, 1.0f, 1.0f, true); for (size_t j = 0; j < length; j++) { t.polyline.append(random_point(LO, HI)); } @@ -45,10 +47,10 @@ SCENARIO("ExtrusionEntityCollection: Polygon flattening") { Slic3r::ExtrusionEntityCollection sub_nosort; sub_nosort.append(nosort_path_set); - sub_nosort.no_sort = true; + sub_nosort.set_can_sort_reverse(true, true); Slic3r::ExtrusionEntityCollection sub_sort; - sub_sort.no_sort = false; + sub_nosort.set_can_sort_reverse(false, false); sub_sort.append(random_paths()); @@ -61,24 +63,24 @@ SCENARIO("ExtrusionEntityCollection: Polygon flattening") { WHEN("The EEC is flattened with default options (preserve_order=false)") { Slic3r::ExtrusionEntityCollection output = Slic3r::FlatenEntities(false).flatten(sample); THEN("The output EEC contains no Extrusion Entity Collections") { - CHECK(std::count_if(output.entities.cbegin(), output.entities.cend(), [=](const ExtrusionEntity* e) {return e->is_collection();}) == 0); + CHECK(std::count_if(output.entities().cbegin(), output.entities().cend(), [=](const ExtrusionEntity* e) {return e->is_collection();}) == 0); } } WHEN("The EEC is flattened with preservation (preserve_order=true)") { Slic3r::ExtrusionEntityCollection output = Slic3r::FlatenEntities(true).flatten(sample); THEN("The output EECs contains one EEC.") { - CHECK(std::count_if(output.entities.cbegin(), output.entities.cend(), [=](const ExtrusionEntity* e) {return e->is_collection();}) == 1); + CHECK(std::count_if(output.entities().cbegin(), output.entities().cend(), [=](const ExtrusionEntity* e) {return e->is_collection();}) == 1); } AND_THEN("The ordered EEC contains the same order of elements than the original") { // find the entity in the collection - for (auto e : output.entities) { + for (auto e : output.entities()) { if (!e->is_collection()) continue; Slic3r::ExtrusionEntityCollection* temp = dynamic_cast(e); // check each Extrusion path against nosort_path_set to see if the first and last match the same - CHECK(nosort_path_set.size() == temp->entities.size()); + CHECK(nosort_path_set.size() == temp->entities().size()); for (size_t i = 0; i < nosort_path_set.size(); i++) { - CHECK(temp->entities[i]->first_point() == nosort_path_set[i].first_point()); - CHECK(temp->entities[i]->last_point() == nosort_path_set[i].last_point()); + CHECK(temp->entities()[i]->first_point() == nosort_path_set[i].first_point()); + CHECK(temp->entities()[i]->last_point() == nosort_path_set[i].last_point()); } } } @@ -100,9 +102,9 @@ SCENARIO("ExtrusionEntityCollection: no sort") { print.process(); //replace extrusion from sliceing by manual ones - print.objects()[0]->clear_layers(); - Layer* customL_layer = print.objects()[0]->add_layer(0, 0.2, 0.2, 0.1); - LayerRegion* custom_region = customL_layer->add_region(print.regions()[0]); + print.objects_mutable()[0]->clear_layers(); + Layer* customL_layer = print.objects_mutable()[0]->add_layer(0, 0.2, 0.2, 0.1); + LayerRegion* custom_region = customL_layer->add_region(&print.get_print_region(0)); ExtrusionPath path_peri(ExtrusionRole::erPerimeter); path_peri.polyline.append(Point{ 0,0 }); @@ -123,7 +125,7 @@ SCENARIO("ExtrusionEntityCollection: no sort") { WHEN("sort") { custom_region->fills.append(coll_fill); custom_region->perimeters.append(coll_peri); - coll_fill.no_sort = false; + coll_fill.set_can_sort_reverse(false, false); Slic3r::Test::gcode(gcode_filepath, print); auto parser{ Slic3r::GCodeReader() }; std::vector extrude_x; @@ -142,7 +144,7 @@ SCENARIO("ExtrusionEntityCollection: no sort") { WHEN("no sort") { - coll_fill.no_sort = true; + coll_fill.set_can_sort_reverse(true, true); custom_region->fills.append(coll_fill); custom_region->perimeters.append(coll_peri); Slic3r::Test::gcode(gcode_filepath, print); diff --git a/tests/superslicerlibslic3r/test_fill.cpp b/tests/superslicerlibslic3r/test_fill.cpp index 17165e94c9a..ce8a70f85e2 100644 --- a/tests/superslicerlibslic3r/test_fill.cpp +++ b/tests/superslicerlibslic3r/test_fill.cpp @@ -1,14 +1,16 @@ //#define CATCH_CONFIG_DISABLE -#include +#include #include "test_data.hpp" #include #include +#include #include #include #include #include +#include using namespace Slic3r; using namespace Slic3r::Geometry; @@ -91,7 +93,7 @@ TEST_CASE("Fill: Pattern Path Length") { filler->angle = angle; Slic3r::ExPolygon e{}; e.contour = Slic3r::Polygon(test_square); - e.holes = Slic3r::Polygons(Slic3r::Polygon(test_hole)); + e.holes = Slic3r::Polygons{Slic3r::Polygon(test_hole)}; Polylines paths {test(e, *filler, params_local)}; //std::cout << "paths.size="<angle = 0.F; Surface surface {(stPosTop|stDensSolid), expolygon}; - Flow flow {0.69f, 0.4f, 0.50f}; + Flow flow = Flow::new_from_width(0.69f, 0.4f, 0.50f, 1.f, false); //width, height, nozzle_diameter, spacing_ratio, is_bridge params.density = 1.0; filler->init_spacing(flow.spacing(), params); @@ -156,10 +158,10 @@ TEST_CASE("Fill: Pattern Path Length") { } SECTION("Solid surface fill") { Points points { - Point::new_scale(6883102, 9598327.01296997), - Point::new_scale(6883102, 20327272.01297), - Point::new_scale(3116896, 20327272.01297), - Point::new_scale(3116896, 9598327.01296997) + Point(6883102, 9598327), + Point(6883102, 20327272), + Point(3116896, 20327272), + Point(3116896, 9598327) }; Slic3r::ExPolygon expolygon{}; expolygon.contour = Slic3r::Polygon{ points }; @@ -169,7 +171,7 @@ TEST_CASE("Fill: Pattern Path Length") { { expolygon.scale(1.05); //FIXME number overflow. - //REQUIRE(test_if_solid_surface_filled(expolygon, 0.55) == true); + REQUIRE(test_if_solid_surface_filled(expolygon, 0.55) == true); } } SECTION("Solid surface fill") { @@ -217,22 +219,144 @@ class ExtrusionGetVolume : public ExtrusionVisitor { void use(ExtrusionMultiPath &multipath) override { for (ExtrusionPath path : multipath.paths) path.visit(*this); } void use(ExtrusionMultiPath3D &multipath) override { for (ExtrusionPath path : multipath.paths) path.visit(*this); } void use(ExtrusionLoop &loop) override { for (ExtrusionPath path : loop.paths) path.visit(*this); } - void use(ExtrusionEntityCollection &collection) override { for (ExtrusionEntity *entity : collection.entities) entity->visit(*this); } + void use(ExtrusionEntityCollection &collection) override { for (ExtrusionEntity *entity : collection.entities()) entity->visit(*this); } double get(ExtrusionEntityCollection &coll) { - for (ExtrusionEntity *entity : coll.entities) entity->visit(*this); + for (ExtrusionEntity *entity : coll.entities()) entity->visit(*this); return volume; } }; +TEST_CASE("Fill area: check if periemter give the good values") +{ + Model model{}; + TriangleMesh sample_mesh = make_cube(5, 5, 0.2); + double volume = (5 * 5 * 0.2); + DynamicPrintConfig &config = Slic3r::DynamicPrintConfig::full_print_config(); + config.set_key_value("perimeters", new ConfigOptionInt(1)); + config.set_key_value("top_solid_layers", new ConfigOptionInt(1)); + config.set_key_value("bottom_solid_layers", new ConfigOptionInt(1)); + + config.set_key_value("enforce_full_fill_volume", new ConfigOptionBool(false)); + config.set_key_value("infill_overlap", new ConfigOptionFloatOrPercent(0.1, false)); + + config.set_key_value("skirts", new ConfigOptionInt(0)); + + config.set_key_value("layer_height", new ConfigOptionFloat(0.2)); // get a known number of layers + config.set_key_value("first_layer_height", new ConfigOptionFloatOrPercent(0.2, false)); + + config.set_key_value("extrusion_width", new ConfigOptionFloatOrPercent(0.5, false)); + config.set_key_value("infill_extrusion_width", new ConfigOptionFloatOrPercent(0.5, false)); + config.set_key_value("perimeter_extrusion_width", new ConfigOptionFloatOrPercent(0.5, false)); + config.set_key_value("first_layer_extrusion_width", new ConfigOptionFloatOrPercent(0.5, false)); + config.set_key_value("external_perimeter_extrusion_width", new ConfigOptionFloatOrPercent(0.5, false)); + config.set_key_value("solid_infill_extrusion_width", new ConfigOptionFloatOrPercent(0.5, false)); + config.set_key_value("top_infill_extrusion_width", new ConfigOptionFloatOrPercent(0.5, false)); + SECTION("no overlap") + { + config.set_key_value("infill_overlap", new ConfigOptionFloatOrPercent(0, false)); + config.set_key_value("external_perimeter_overlap", new ConfigOptionPercent(0)); + config.set_key_value("solid_infill_overlap", new ConfigOptionPercent(0)); + Print print{}; + Slic3r::Test::init_print(print, { sample_mesh }, model, &config); + print.process(); + const LayerRegion *lr = print.get_object(0)->get_layer(0)->regions()[0]; + double area_infill = unscaled(unscaled(lr->fill_surfaces.surfaces.front().area())); + REQUIRE(lr->fill_no_overlap_expolygons.empty()); + double area_computed = (5-0.5*2) * (5-0.5*2); + REQUIRE(std::abs(area_computed - area_infill) < 0.001); + } + SECTION("only encroachment (0.2mm)") + { + config.set_key_value("infill_overlap", new ConfigOptionFloatOrPercent(0.2, false)); + config.set_key_value("external_perimeter_overlap", new ConfigOptionPercent(0)); + config.set_key_value("perimeter_overlap", new ConfigOptionPercent(100)); + config.set_key_value("solid_infill_overlap", new ConfigOptionPercent(0)); + Print print{}; + Slic3r::Test::init_print(print, { sample_mesh }, model, &config); + print.process(); + const LayerRegion *lr = print.get_object(0)->get_layer(0)->regions()[0]; + REQUIRE(1 == lr->fill_surfaces.surfaces.size()); + REQUIRE(1 == lr->fill_no_overlap_expolygons.size()); + double area_infill = unscaled(unscaled(lr->fill_surfaces.surfaces[0].area())); + double area_infill_no_overlap = unscaled(unscaled(lr->fill_no_overlap_expolygons[0].area())); // note: don't need to intersect as there is only one fill_surfaces + double area_no_encroach_computed = (5-0.5*2) * (5-0.5*2); + double area_computed = (5-0.3*2) * (5-0.3*2); + REQUIRE(area_infill_no_overlap < area_infill); + REQUIRE(std::abs(area_computed - area_infill) < 0.001); + REQUIRE(std::abs(area_no_encroach_computed - area_infill_no_overlap) < 0.001); + } + SECTION("only encroachment (40%)") + { + // % over (perimeter_spacing + solid_fill_spacing)/2, but no periemter overlap + // (note: here it's the external perimeter, as we have only one perimeter) + config.set_key_value("infill_overlap", new ConfigOptionFloatOrPercent(40, true)); // 40% -> 0.2 value + config.set_key_value("external_perimeter_overlap", new ConfigOptionPercent(0)); + config.set_key_value("perimeter_overlap", new ConfigOptionPercent(100)); + config.set_key_value("solid_infill_overlap", new ConfigOptionPercent(0)); + Print print{}; + Slic3r::Test::init_print(print, { sample_mesh }, model, &config); + print.process(); + const LayerRegion *lr = print.get_object(0)->get_layer(0)->regions()[0]; + REQUIRE(1 == lr->fill_surfaces.surfaces.size()); + REQUIRE(1 == lr->fill_no_overlap_expolygons.size()); + double area_infill = unscaled(unscaled(lr->fill_surfaces.surfaces[0].area())); + double area_infill_no_overlap = unscaled(unscaled(lr->fill_no_overlap_expolygons[0].area())); // note: don't need to intersect as there is only one fill_surfaces + double area_no_encroach_computed = (5-0.5*2) * (5-0.5*2); + double area_computed = (5-0.3*2) * (5-0.3*2); + REQUIRE(area_infill_no_overlap < area_infill); + REQUIRE(std::abs(area_computed - area_infill) < 0.001); + REQUIRE(std::abs(area_no_encroach_computed - area_infill_no_overlap) < 0.001); + } + SECTION("only overlap") + { + config.set_key_value("infill_overlap", new ConfigOptionFloatOrPercent(0, false)); + config.set_key_value("external_perimeter_overlap", new ConfigOptionPercent(100)); + config.set_key_value("perimeter_overlap", new ConfigOptionPercent(100)); + config.set_key_value("solid_infill_overlap", new ConfigOptionPercent(100)); + Print print{}; + Slic3r::Test::init_print(print, { sample_mesh }, model, &config); + print.process(); + const LayerRegion *lr = print.get_object(0)->get_layer(0)->regions()[0]; + REQUIRE(1 == lr->fill_surfaces.surfaces.size()); + REQUIRE(lr->fill_no_overlap_expolygons.empty()); + double area_infill = unscaled(unscaled(lr->fill_surfaces.surfaces[0].area())); + double spacing_diff = (0.5f - Flow::rounded_rectangle_extrusion_spacing(0.5f, 0.2f, 1.f))/2; + double area_computed = (5-(0.5-spacing_diff)*2) * (5-(0.5-spacing_diff)*2); + REQUIRE(std::abs(area_computed - area_infill) < 0.001); + } + SECTION("both") + { + config.set_key_value("infill_overlap", new ConfigOptionFloatOrPercent(0.1, false)); + config.set_key_value("external_perimeter_overlap", new ConfigOptionPercent(100)); + config.set_key_value("perimeter_overlap", new ConfigOptionPercent(100)); + config.set_key_value("solid_infill_overlap", new ConfigOptionPercent(100)); + Print print{}; + Slic3r::Test::init_print(print, { sample_mesh }, model, &config); + print.process(); + const LayerRegion *lr = print.get_object(0)->get_layer(0)->regions()[0]; + REQUIRE(1 == lr->fill_surfaces.surfaces.size()); + REQUIRE(1 == lr->fill_no_overlap_expolygons.size()); + double area_infill = unscaled(unscaled(lr->fill_surfaces.surfaces[0].area())); + double area_infill_no_overlap = unscaled(unscaled(lr->fill_no_overlap_expolygons[0].area())); // note: don't need to intersect as there is only one fill_surfaces + double spacing_diff = (0.5f - Flow::rounded_rectangle_extrusion_spacing(0.5f, 0.2f, 1.f))/2; + double area_no_encroach_computed = (5-(0.5-spacing_diff)*2) * (5-(0.5-spacing_diff)*2); + double area_computed = (5-(0.4-spacing_diff)*2) * (5-(0.4-spacing_diff)*2); + REQUIRE(area_infill_no_overlap < area_infill); + REQUIRE(std::abs(area_computed - area_infill) < 0.001); + REQUIRE(std::abs(area_no_encroach_computed - area_infill_no_overlap) < 0.001); + } +} + #include "libslic3r/GCodeReader.hpp" TEST_CASE("Fill: extrude gcode and check it") { - SECTION("simple square") { + SECTION("simple square") + { Model model{}; TriangleMesh sample_mesh = make_cube(5, 5, 0.2); double volume = (5 * 5 * 0.2); - sample_mesh.repair(); + //sample_mesh.repair(); DynamicPrintConfig &config = Slic3r::DynamicPrintConfig::full_print_config(); config.set_key_value("perimeters", new ConfigOptionInt(1)); @@ -240,7 +364,10 @@ TEST_CASE("Fill: extrude gcode and check it") config.set_key_value("bottom_solid_layers", new ConfigOptionInt(1)); config.set_key_value("enforce_full_fill_volume", new ConfigOptionBool(true)); - config.set_key_value("infill_overlap", new ConfigOptionFloatOrPercent(0.1, true)); + config.set_key_value("infill_overlap", new ConfigOptionFloatOrPercent(0.1, false)); + config.set_key_value("external_perimeter_overlap", new ConfigOptionPercent(100)); + config.set_key_value("perimeter_overlap", new ConfigOptionPercent(100)); + config.set_key_value("solid_infill_overlap", new ConfigOptionPercent(100)); config.set_key_value("skirts", new ConfigOptionInt(0)); @@ -264,6 +391,8 @@ TEST_CASE("Fill: extrude gcode and check it") Slic3r::Test::gcode(gcode_filepath, print); //std::cout << "gcode generation done\n"; std::string gcode_from_file = read_to_string(gcode_filepath); + model = print.model(); + Slic3r::store_3mf("test.3mf", &model, &print.full_print_config(), OptionStore3mf{}); //string[] lineArray = gcode_from_file GCodeReader parser; @@ -288,29 +417,42 @@ TEST_CASE("Fill: extrude gcode and check it") } }); - double perimeterRoundGapRemove = unscaled(print.objects()[0]->layers()[0]->lslices[0].contour.length()) * 0.1*0.1 * (2 - (PI / 2)); - double perimeterRoundGapAdd = unscaled(print.objects()[0]->layers()[0]->lslices[0].contour.length()) * 0.1*0.1 * ((PI / 2)); - //for (Line &l : print.objects()[0]->layers()[0]->slices.expolygons[0].contour.lines()) { + ExPolygons perimeter_center_line = offset_ex(print.get_object(0)->get_layer(0)->lslices[0], -scale_t(0.25f)); + + //double perimeterRoundGapRemove = unscaled(print.get_object(0)->get_layer(0)->lslices[0].contour.length()) * 0.1*0.1 * (2 - (PI / 2)); + double perimeterRoundGapRemove = unscaled(perimeter_center_line[0].contour.length()) * 0.1*0.1 * (2 - (PI / 2)); + //double perimeterRoundGapAdd = unscaled(print.get_object(0)->get_layer(0)->lslices[0].contour.length()) * 0.1*0.1 * ((PI / 2)); + //for (Line &l : print.get_object(0)->get_layer(0)->slices.expolygons[0].contour.lines()) { //} //std::cout << "flow mm3permm: " << Flow{ 0.5f,0.2f,0.4f,false }.mm3_per_mm() << "\n"; - //std::cout << "perimeter : " << unscaled(print.objects()[0]->layers()[0]->slices.expolygons[0].contour.length()) << " != " << (PI * 10) << "\n"; + //std::cout << "perimeter : " << unscaled(print.get_object(0)->get_layer(0)->slices.expolygons[0].contour.length()) << " != " << (PI * 10) << "\n"; //std::cout << "created a mesh of volume " << volume << " and i have extruded " << volume_extruded << " mm3.\n"; //std::cout << "Note that if we remove the bits of the external extrusion, it's only a volume of " << (volume - perimeterRoundGapRemove) << " that needs to be filled\n"; //std::cout << "Note that if we add the bits of the external extrusion, it's a volume of " << (volume + perimeterRoundGapAdd) << " that needs to be filled\n"; - double volumeExtrPerimeter = ExtrusionGetVolume{}.get(print.objects()[0]->layers()[0]->regions()[0]->perimeters); - double volumeExtrInfill = ExtrusionGetVolume{}.get(print.objects()[0]->layers()[0]->regions()[0]->fills); + double volumeExtrPerimeter = ExtrusionGetVolume{}.get(print.get_object(0)->get_layer(0)->regions()[0]->perimeters); + double volumeExtrInfill = ExtrusionGetVolume{}.get(print.get_object(0)->get_layer(0)->regions()[0]->fills); double volumeInfill = 0; - for (const ExPolygon & p : print.objects()[0]->layers()[0]->regions()[0]->fill_no_overlap_expolygons) { + for (const ExPolygon & p : print.get_object(0)->get_layer(0)->regions()[0]->fill_no_overlap_expolygons) { volumeInfill += unscaled(unscaled(p.area())); } - volumeInfill *= 0.2;/* - std::cout << "volumeRealr=" << (volume_perimeter_extruded + volume_infill_extruded) << " volumeRealPerimeter= " << volume_perimeter_extruded << " and volumeRealInfill=" << volume_infill_extruded << " mm3." << "\n"; + double spacing_diff = (0.5f - Flow::rounded_rectangle_extrusion_spacing(0.5f, 0.2f, 1.f))/2; + double raw_area_no_encroach = (5-(0.5-spacing_diff)*2) * (5-(0.5-spacing_diff)*2); + double raw_area = (5-(0.4-spacing_diff)*2) * (5-(0.4-spacing_diff)*2); + + double compute_perimeter_area = 4.5*4*Flow::rounded_rectangle_extrusion_spacing(0.5f, 0.2f, 1.f); + + std::cout << "area fill_no_overlap_expolygons= " << (unscaled(unscaled(print.get_object(0)->get_layer(0)->regions()[0]->fill_no_overlap_expolygons.front().contour.area()))) << "\n"; + volumeInfill *= 0.2; + std::cout << "\nvolumeRealr=" << (volume_perimeter_extruded + volume_infill_extruded) << " volumeRealPerimeter= " << volume_perimeter_extruded << " and volumeRealInfill=" << volume_infill_extruded << " mm3." << "\n"; std::cout << "volumeExtr=" << (volumeExtrPerimeter + volumeExtrInfill) << " volumeExtrPerimeter= " << volumeExtrPerimeter << " and volumeExtrInfill=" << volumeExtrInfill << " mm3." << "\n"; - std::cout << "volumePerimeter= " << (volume - volumeInfill) << " volumePerimeter(wo/bits)= " << (volume - volumeInfill- perimeterRoundGapRemove) << " and volumeInfill=" << volumeInfill << " mm3." << "\n";*/ + std::cout << "volumePerimeter= " << (volume - volumeInfill) << " volumePerimeter(wo/bits)= " << (volume - volumeInfill- perimeterRoundGapRemove) << " and volumeInfill=" << volumeInfill << " mm3." << "\n"; + std::cout << "volume= " << (volume) << " raw_fill_volume="<layers()[0]->slices.expolygons[0].contour, "green"); - // svg.draw(print.objects()[0]->layers()[0]->regions()[0]->fill_no_overlap_expolygons, "black", scale_(0.01)); - // svg.draw(print.objects()[0]->layers()[0]->regions()[0]->perimeters.as_polylines(), "orange", fl.scaled_width()); - // svg.draw(print.objects()[0]->layers()[0]->regions()[0]->perimeters.as_polylines(), "red", fl.scaled_spacing()); - // svg.draw(print.objects()[0]->layers()[0]->regions()[0]->fills.as_polylines(), "cyan", fl.scaled_width()); - // svg.draw(print.objects()[0]->layers()[0]->regions()[0]->fills.as_polylines(), "blue", fl.scaled_spacing()); + // svg.draw(print.get_object(0)->get_layer(0)->slices.expolygons[0].contour, "green"); + // svg.draw(print.get_object(0)->get_layer(0)->regions()[0]->fill_no_overlap_expolygons, "black", scale_(0.01)); + // svg.draw(print.get_object(0)->get_layer(0)->regions()[0]->perimeters.as_polylines(), "orange", fl.scaled_width()); + // svg.draw(print.get_object(0)->get_layer(0)->regions()[0]->perimeters.as_polylines(), "red", fl.scaled_spacing()); + // svg.draw(print.get_object(0)->get_layer(0)->regions()[0]->fills.as_polylines(), "cyan", fl.scaled_width()); + // svg.draw(print.get_object(0)->get_layer(0)->regions()[0]->fills.as_polylines(), "blue", fl.scaled_spacing()); // svg.Close(); //} + REQUIRE(abs(raw_area_no_encroach*0.2 - volumeInfill) < 0.01); + REQUIRE(abs(compute_perimeter_area * 0.2 - volumeExtrPerimeter) < 0.01); //std::cout << gcode_from_file; REQUIRE(abs(volumeInfill - volumeExtrInfill) < EPSILON); @@ -339,8 +483,7 @@ TEST_CASE("Fill: extrude gcode and check it") SECTION("simple disk") { Model model{}; TriangleMesh sample_mesh = make_cylinder(5, 0.2); - double volume = (PI * 25 * 0.2); - sample_mesh.repair(); + const double volume = (PI * 25 * 0.2); DynamicPrintConfig &config = Slic3r::DynamicPrintConfig::full_print_config(); config.set_key_value("perimeters", new ConfigOptionInt(1)); @@ -349,6 +492,9 @@ TEST_CASE("Fill: extrude gcode and check it") config.set_key_value("enforce_full_fill_volume", new ConfigOptionBool(true)); config.set_key_value("infill_overlap", new ConfigOptionFloatOrPercent(0.1, true)); + config.set_key_value("perimeter_overlap", new ConfigOptionPercent(100)); + config.set_key_value("external_perimeter_overlap", new ConfigOptionPercent(100)); + config.set_deserialize("external_perimeter_cut_corners", "0"); config.set_key_value("skirts", new ConfigOptionInt(0)); @@ -376,45 +522,54 @@ TEST_CASE("Fill: extrude gcode and check it") //string[] lineArray = gcode_from_file GCodeReader parser; double volume_extruded = 0; - int idx = 0; + //int idx = 0; + int step = 0; double volume_perimeter_extruded = 0; double volume_infill_extruded = 0; // add remaining time lines where needed parser.parse_buffer(gcode_from_file, [&](GCodeReader& reader, const GCodeReader::GCodeLine& line) { - if (line.cmd_is("G1")) + if(line.comment() == "TYPE:External perimeter") + step = 1; + if(line.comment() == "TYPE:Solid infill") + step = 2; + if (line.cmd_is("G1") && step > 0) { if (line.dist_E(reader) > 0 && line.dist_XY(reader) > 0) { //std::cout << "add " << line.dist_E(reader)<<" now "<< volume_extruded<<"=>"; volume_extruded += line.dist_E(reader)*(PI*1.75*1.75 / 4.); //std::cout << volume_extruded << "\n"; - if (idx<36)volume_perimeter_extruded += line.dist_E(reader)*(PI*1.75*1.75 / 4.); - else volume_infill_extruded += line.dist_E(reader)*(PI*1.75*1.75 / 4.); - idx++; + if (step == 1) volume_perimeter_extruded += line.dist_E(reader)*(PI*1.75*1.75 / 4.); + else if (step == 2) volume_infill_extruded += line.dist_E(reader)*(PI*1.75*1.75 / 4.); } } }); - double perimeterRoundGapRemove = unscaled(print.objects()[0]->layers()[0]->lslices[0].contour.length()) * 0.1*0.1 * (2 - (PI / 2)); - double perimeterRoundGapAdd = unscaled(print.objects()[0]->layers()[0]->lslices[0].contour.length()) * 0.1*0.1 * ((PI / 2)); + ExPolygons perimeter_center_line = offset_ex(print.get_object(0)->get_layer(0)->lslices[0], -scale_t(0.25f)); - double volumeExtrPerimeter = ExtrusionGetVolume{}.get(print.objects()[0]->layers()[0]->regions()[0]->perimeters); - double volumeExtrInfill = ExtrusionGetVolume{}.get(print.objects()[0]->layers()[0]->regions()[0]->fills); + //double perimeterRoundGapRemove = unscaled(print.get_object(0)->get_layer(0)->lslices[0].contour.length()) * 0.1*0.1 * (2 - (PI / 2)); + double perimeterRoundGapRemove = unscaled(perimeter_center_line[0].contour.length()) * 0.1*0.1 * (2 - (PI / 2)); + //double perimeterRoundGapAdd = unscaled(print.get_object(0)->get_layer(0)->lslices[0].contour.length()) * 0.1*0.1 * ((PI / 2)); + + double volumeExtrPerimeter = ExtrusionGetVolume{}.get(print.get_object(0)->get_layer(0)->regions()[0]->perimeters); + double volumeExtrInfill = ExtrusionGetVolume{}.get(print.get_object(0)->get_layer(0)->regions()[0]->fills); double volumeInfill = 0; - for (const ExPolygon & p : print.objects()[0]->layers()[0]->regions()[0]->fill_no_overlap_expolygons) { + ExPolygons infill_area = intersection_ex(print.get_object(0)->get_layer(0)->regions()[0]->fill_no_overlap_expolygons, print.get_object(0)->get_layer(0)->regions()[0]->fill_expolygons); + for (const ExPolygon & p : infill_area) { volumeInfill += unscaled(unscaled(p.area())); } volumeInfill *= 0.2; std::cout << "volumeRealr=" << (volume_perimeter_extruded + volume_infill_extruded) << " volumeRealPerimeter= " << volume_perimeter_extruded << " and volumeRealInfill=" << volume_infill_extruded << " mm3." << "\n"; std::cout << "volumeExtr=" << (volumeExtrPerimeter + volumeExtrInfill) << " volumeExtrPerimeter= " << volumeExtrPerimeter << " and volumeExtrInfill=" << volumeExtrInfill << " mm3." << "\n"; std::cout << "volumePerimeter= " << (volume - volumeInfill) << " volumePerimeter(wo/bits)= " << (volume - volumeInfill - perimeterRoundGapRemove) << " and volumeInfill=" << volumeInfill << " mm3." << "\n"; + std::cout << "volume= " << (volume) << "\n"; - REQUIRE(abs(volumeInfill - volumeExtrInfill) < EPSILON); - REQUIRE(abs(volumeInfill - volume_infill_extruded) < 0.01); - REQUIRE(abs((volume - volumeInfill - perimeterRoundGapRemove) - volumeExtrPerimeter) < EPSILON); - REQUIRE(abs((volume - volumeInfill - perimeterRoundGapRemove) - volume_perimeter_extruded) < 0.1); //there are a bit less for seam mitigation + REQUIRE(abs(volumeInfill - volumeExtrInfill) < 0.001); + REQUIRE(abs(volumeInfill - volume_infill_extruded) < 0.001); + REQUIRE(abs((volume - volumeInfill - perimeterRoundGapRemove) - volumeExtrPerimeter) < 0.1); //there are a bit less for seam mitigation + REQUIRE(abs(volumeExtrPerimeter - volume_perimeter_extruded) < 0.01); clean_file(gcode_filepath, "gcode"); } @@ -660,6 +815,23 @@ for my $pattern (qw(rectilinear honeycomb hilbertcurve concentric)) { } */ +class ExtrusionGetExtrusionArea : public ExtrusionVisitor { + Polygons grown_paths; +public: + ExtrusionGetExtrusionArea() {} + void use(ExtrusionPath &path) override { + polygons_append(grown_paths, offset(path.as_polyline().as_polyline(), scale_t(path.width))); + } + void use(ExtrusionPath3D &path3D) override { assert(false); } + void use(ExtrusionMultiPath &multipath) override { for (ExtrusionPath path : multipath.paths) path.visit(*this); } + void use(ExtrusionMultiPath3D &multipath) override { for (ExtrusionPath path : multipath.paths) path.visit(*this); } + void use(ExtrusionLoop &loop) override { for (ExtrusionPath path : loop.paths) path.visit(*this); } + void use(ExtrusionEntityCollection &collection) override { for (ExtrusionEntity *entity : collection.entities()) entity->visit(*this); } + Polygons get(ExtrusionEntityCollection &coll) { + for (ExtrusionEntity *entity : coll.entities()) entity->visit(*this); + return grown_paths; + } +}; //TODO: also check by volume extruded //TODO: replace the simple area coverage check by one that takes into account the width of the path, not only the default flow spacing //TODO: test more fills @@ -669,26 +841,31 @@ bool test_if_solid_surface_filled(const ExPolygon& expolygon, double flow_width, filler->angle = angle; FillParams params; params.dont_adjust = false; + FullPrintConfig config= FullPrintConfig::defaults(); + params.config = &config; Surface surface((stPosBottom | stDensSolid), expolygon); //note: here we do flow.width = flow_width , flow.gheight = 0.4, flow.nozzle_size = flow_width; - Flow flow(flow_width, 0.4, flow_width); + params.flow = Flow::new_from_width( float(flow_width), 0.4, float(flow_width), 1.f, false); params.density = density; - filler->init_spacing(flow.spacing(), params); + filler->init_spacing(params.flow.spacing(), params); - Polylines paths {filler->fill_surface(&surface, params)}; + // concentricgapfill can't output only Polylines, as it's a composed thing with gapfill + //Polylines paths {filler->fill_surface(&surface, params)}; + ExtrusionEntityCollection coll; + filler->fill_surface_extrusion(&surface, params, coll.set_entities()); // check whether any part was left uncovered - Polygons grown_paths; - grown_paths.reserve(paths.size()); // figure out what is actually going on here re: data types - std::for_each(paths.begin(), paths.end(), [filler, &grown_paths] (const Slic3r::Polyline& p) { - polygons_append(grown_paths, offset(p, scale_(filler->get_spacing() / 2.0))); - }); + Polygons grown_paths = ExtrusionGetExtrusionArea{}.get(coll); + //grown_paths.reserve(paths.size()); + //std::for_each(paths.begin(), paths.end(), [filler, &grown_paths] (const Slic3r::Polyline& p) { + // polygons_append(grown_paths, offset(p, scale_(filler->get_spacing() / 2.0))); + //}); - ExPolygons uncovered = diff_ex(expolygon, grown_paths, true); + ExPolygons uncovered = diff_ex(expolygon, grown_paths, Slic3r::ApplySafetyOffset::Yes); // ignore very small dots const auto scaled_flow_width { std::pow(scale_(flow_width), 2) }; @@ -700,6 +877,6 @@ bool test_if_solid_surface_filled(const ExPolygon& expolygon, double flow_width, double uncovered_area = 0; for (ExPolygon &p : uncovered) uncovered_area += unscaled(unscaled(p.area())); std::cout << "uncovered size =" << uncovered_area << " / "<< unscaled(unscaled(expolygon.area()))<<"\n"; - return uncovered.size() == 0; // solid surface is fully filled + return uncovered_area < 0.05; // solid surface is (almost) fully filled } diff --git a/tests/superslicerlibslic3r/test_flow.cpp b/tests/superslicerlibslic3r/test_flow.cpp index e3e5f97ab66..7d4c7db16e9 100644 --- a/tests/superslicerlibslic3r/test_flow.cpp +++ b/tests/superslicerlibslic3r/test_flow.cpp @@ -1,7 +1,7 @@ //#define CATCH_CONFIG_DISABLE -#include +#include #include #include @@ -104,8 +104,11 @@ SCENARIO(" Bridge flow specifics.", "[!mayfail]") { /// Test the expected behavior for auto-width, /// spacing, etc SCENARIO("Flow: Flow math for non-bridges", "[!mayfail]") { + auto width_0 = ConfigOptionFloatOrPercent(1.0, false); + auto spacing_0 = ConfigOptionFloatOrPercent(1.0, false,true); GIVEN("Nozzle Diameter of 0.4, a desired width of 1mm and layer height of 0.5") { - auto width {ConfigOptionFloatOrPercent{1.0, false}}; + auto width_1 = ConfigOptionFloatOrPercent(1.0, false); + auto spacing_1 = ConfigOptionFloatOrPercent(1.0, false,true); float spacing {0.4f}; float nozzle_diameter {0.4f}; float bridge_flow {1.0f}; @@ -113,19 +116,19 @@ SCENARIO("Flow: Flow math for non-bridges", "[!mayfail]") { // Spacing for non-bridges is has some overlap THEN("External perimeter flow has a default spacing fixed to 1.05*nozzle_diameter") { - Flow flow {Flow::new_from_config_width(frExternalPerimeter, ConfigOptionFloatOrPercent{0, false}, nozzle_diameter, layer_height, 0.0f)}; + Flow flow = Flow::new_from_config_width(frExternalPerimeter, width_0, spacing_0, nozzle_diameter, layer_height, 0.0f); REQUIRE(flow.spacing() == Approx((1.05f*nozzle_diameter) - layer_height * (1.0 - PI / 4.0))); } THEN("Internal perimeter flow has a default spacing fixed to 1.125*nozzle_diameter") { - Flow flow {Flow::new_from_config_width(frPerimeter, ConfigOptionFloatOrPercent{0, false}, nozzle_diameter, layer_height, 0.0f)}; + Flow flow {Flow::new_from_config_width(frPerimeter, width_0, spacing_0, nozzle_diameter, layer_height, 0.0f)}; REQUIRE(flow.spacing() == Approx((1.125*nozzle_diameter) - layer_height * (1.0 - PI / 4.0))); } THEN("Spacing for supplied width is 0.8927f") { - Flow flow {Flow::new_from_config_width(frExternalPerimeter, width, nozzle_diameter, layer_height, 0.0f)}; - REQUIRE(flow.spacing() == Approx(width - layer_height * (1.0 - PI / 4.0))); - flow = Flow::new_from_config_width(frPerimeter, width, nozzle_diameter, layer_height, 0.0f); - REQUIRE(flow.spacing() == Approx(width - layer_height * (1.0 - PI / 4.0))); + Flow flow {Flow::new_from_config_width(frExternalPerimeter, width_1, spacing_1, nozzle_diameter, layer_height, 0.0f)}; + REQUIRE(flow.spacing() == Approx(width_1.get_abs_value(1.f) - layer_height * (1.0 - PI / 4.0))); + flow = Flow::new_from_config_width(frPerimeter, width_1, spacing_1, nozzle_diameter, layer_height, 0.0f); + REQUIRE(flow.spacing() == Approx(width_1.get_abs_value(1.f) - layer_height * (1.0 - PI / 4.0))); } } /// Check the min/max @@ -135,23 +138,23 @@ SCENARIO("Flow: Flow math for non-bridges", "[!mayfail]") { WHEN("layer height is set to 0.15") { layer_height = 5.f; THEN("Max width is respected.") { - auto flow {Flow::new_from_config_width(frPerimeter, ConfigOptionFloatOrPercent{0, false}, nozzle_diameter, layer_height, 0.0f)}; - REQUIRE(flow.width <= Approx(1.4*nozzle_diameter)); + auto flow {Flow::new_from_config_width(frPerimeter, width_0, spacing_0, nozzle_diameter, layer_height, 0.0f)}; + REQUIRE(flow.width() <= Approx(1.4*nozzle_diameter)); } THEN("Min width is respected") { - auto flow{ Flow::new_from_config_width(frPerimeter, ConfigOptionFloatOrPercent{0, false}, nozzle_diameter, layer_height, 0.0f) }; - REQUIRE(flow.width >= Approx(1.05*nozzle_diameter)); + auto flow{ Flow::new_from_config_width(frPerimeter, width_0, spacing_0, nozzle_diameter, layer_height, 0.0f) }; + REQUIRE(flow.width() >= Approx(1.05*nozzle_diameter)); } } WHEN("Layer height is set to 0.3") { layer_height = 0.01f; THEN("Max width is respected.") { - auto flow{ Flow::new_from_config_width(frPerimeter, ConfigOptionFloatOrPercent{0, false}, nozzle_diameter, layer_height, 0.0f) }; - REQUIRE(flow.width <= Approx(1.4*nozzle_diameter)); + auto flow{ Flow::new_from_config_width(frPerimeter, width_0, spacing_0, nozzle_diameter, layer_height, 0.0f) }; + REQUIRE(flow.width() <= Approx(1.4*nozzle_diameter)); } THEN("Min width is respected.") { - auto flow{ Flow::new_from_config_width(frPerimeter, ConfigOptionFloatOrPercent{0, false}, nozzle_diameter, layer_height, 0.0f) }; - REQUIRE(flow.width >= Approx(1.05*nozzle_diameter)); + auto flow{ Flow::new_from_config_width(frPerimeter, width_0, spacing_0, nozzle_diameter, layer_height, 0.0f) }; + REQUIRE(flow.width() >= Approx(1.05*nozzle_diameter)); } } } @@ -176,42 +179,43 @@ SCENARIO("Flow: Flow math for non-bridges", "[!mayfail]") { /// Spacing, width calculation for bridge extrusions SCENARIO("Flow: Flow math for bridges", "[!mayfail]") { GIVEN("Nozzle Diameter of 0.4, a desired width of 1mm and layer height of 0.5") { + float BRIDGE_EXTRA_SPACING_MULT = 0.f; // not used anymore auto width {ConfigOptionFloatOrPercent{1.0, false}}; - auto spacing {0.4}; - auto nozzle_diameter {0.4}; - auto bridge_flow {1.0}; - auto layer_height {0.5}; + auto spacing = ConfigOptionFloatOrPercent(1.0, false, false); + float nozzle_diameter {0.4f}; + float spacing_ratio {1.0f}; + float layer_height {0.5f}; WHEN("Flow role is frExternalPerimeter") { - auto flow {Flow::new_from_config_width(frExternalPerimeter, width, nozzle_diameter, layer_height, bridge_flow)}; + auto flow {Flow::new_from_config_width(frExternalPerimeter, width, spacing, nozzle_diameter, layer_height, spacing_ratio)}; THEN("Bridge width is same as nozzle diameter") { - REQUIRE(flow.width == Approx(nozzle_diameter)); + REQUIRE(flow.width() == Approx(nozzle_diameter)); } THEN("Bridge spacing is same as nozzle diameter + BRIDGE_EXTRA_SPACING_MULT * nozzle_diameter") { REQUIRE(flow.spacing() == Approx(nozzle_diameter + BRIDGE_EXTRA_SPACING_MULT * nozzle_diameter)); } } WHEN("Flow role is frInfill") { - auto flow {Flow::new_from_config_width(frInfill, width, nozzle_diameter, layer_height, bridge_flow)}; + auto flow {Flow::new_from_config_width(frInfill, width, spacing, nozzle_diameter, layer_height, spacing_ratio)}; THEN("Bridge width is same as nozzle diameter") { - REQUIRE(flow.width == Approx(nozzle_diameter)); + REQUIRE(flow.width() == Approx(nozzle_diameter)); } THEN("Bridge spacing is same as nozzle diameter + BRIDGE_EXTRA_SPACING_MULT * nozzle_diameter") { REQUIRE(flow.spacing() == Approx(nozzle_diameter + BRIDGE_EXTRA_SPACING_MULT * nozzle_diameter)); } } WHEN("Flow role is frPerimeter") { - auto flow {Flow::new_from_config_width(frPerimeter, width, nozzle_diameter, layer_height, bridge_flow)}; + auto flow {Flow::new_from_config_width(frPerimeter, width, spacing, nozzle_diameter, layer_height, spacing_ratio)}; THEN("Bridge width is same as nozzle diameter") { - REQUIRE(flow.width == Approx(nozzle_diameter)); + REQUIRE(flow.width() == Approx(nozzle_diameter)); } THEN("Bridge spacing is same as nozzle diameter + BRIDGE_EXTRA_SPACING_MULT * nozzle_diameter") { REQUIRE(flow.spacing() == Approx(nozzle_diameter + BRIDGE_EXTRA_SPACING_MULT * nozzle_diameter)); } } WHEN("Flow role is frSupportMaterial") { - auto flow {Flow::new_from_config_width(frSupportMaterial, width, nozzle_diameter, layer_height, bridge_flow)}; + auto flow {Flow::new_from_config_width(frSupportMaterial, width, spacing, nozzle_diameter, layer_height, spacing_ratio)}; THEN("Bridge width is same as nozzle diameter") { - REQUIRE(flow.width == Approx(nozzle_diameter)); + REQUIRE(flow.width() == Approx(nozzle_diameter)); } THEN("Bridge spacing is same as nozzle diameter + BRIDGE_EXTRA_SPACING_MULT * nozzle_diameter") { REQUIRE(flow.spacing() == Approx(nozzle_diameter + BRIDGE_EXTRA_SPACING_MULT * nozzle_diameter)); diff --git a/tests/superslicerlibslic3r/test_gcodewriter.cpp b/tests/superslicerlibslic3r/test_gcodewriter.cpp index 58e4225af02..3a93d85768d 100644 --- a/tests/superslicerlibslic3r/test_gcodewriter.cpp +++ b/tests/superslicerlibslic3r/test_gcodewriter.cpp @@ -1,7 +1,7 @@ //#define CATCH_CONFIG_DISABLE -#include +#include #include #include "libslic3r/GCodeWriter.hpp" @@ -9,8 +9,6 @@ #include #include //#include "test_data.hpp" // get access to init_print, etc -#define PRECISION(val, precision) std::fixed << std::setprecision(precision) << val -#define XYZF_NUM(val) PRECISION(val, 3) using namespace Slic3r; using namespace std::literals::string_literals; @@ -22,17 +20,20 @@ SCENARIO("lift() and unlift() behavior with large values of Z", "[!shouldfail]") GCodeWriter writer{}; GCodeConfig& config {writer.config}; config.set_defaults(); - config.load(std::string{ TEST_DATA_DIR PATH_SEPARATOR } +"test_gcodewriter/config_lift_unlift.ini"s); + config.load(std::string{ TEST_DATA_DIR PATH_SEPARATOR } +"fff_print_tests/test_gcodewriter/config_lift_unlift.ini"s, Slic3r::ForwardCompatibilitySubstitutionRule::Disable); + assert(!config.retract_lift.values.empty() && config.retract_lift.values.front() > 0); std::vector extruder_ids {0}; writer.set_extruders(extruder_ids); writer.set_tool(0); + int lift_layer_id = 1; // not first layer, as lift is deactivated on it by default WHEN("Z is set to 9007199254740992") { double trouble_Z{ 9007199254740992 }; - writer.travel_to_z(trouble_Z); + const std::string travel_str = writer.travel_to_z(trouble_Z); + REQUIRE(travel_str.size() > 0); AND_WHEN("GcodeWriter::Lift() is called") { - const std::string lift = writer.lift(); + const std::string lift = writer.lift(lift_layer_id); REQUIRE(lift.size() > 0); AND_WHEN("Z is moved post-lift to the same delta as the config Z lift") { REQUIRE(writer.travel_to_z(trouble_Z + config.retract_lift.values[0]).size() == 0); @@ -40,7 +41,7 @@ SCENARIO("lift() and unlift() behavior with large values of Z", "[!shouldfail]") const std::string unlift = writer.unlift(); REQUIRE(unlift.size() == 0); // we're the same height so no additional move happens. THEN("GCodeWriter::Lift() emits gcode.") { - const std::string lift_again = writer.lift(); + const std::string lift_again = writer.lift(lift_layer_id); REQUIRE(lift_again.size() > 0); } } @@ -55,23 +56,24 @@ SCENARIO("lift() is not ignored after unlift() at normal values of Z") { GCodeWriter writer{}; GCodeConfig& config {writer.config}; config.set_defaults(); - config.load(std::string{ TEST_DATA_DIR PATH_SEPARATOR } +"test_gcodewriter/config_lift_unlift.ini"s); + config.load(std::string{ TEST_DATA_DIR PATH_SEPARATOR } +"fff_print_tests/test_gcodewriter/config_lift_unlift.ini"s, Slic3r::ForwardCompatibilitySubstitutionRule::Disable); std::vector extruder_ids {0}; writer.set_extruders(extruder_ids); writer.set_tool(0); + int lift_layer_id = 1; WHEN("Z is set to 203") { double trouble_Z{ 203 }; writer.travel_to_z(trouble_Z); AND_WHEN("GcodeWriter::Lift() is called") { - REQUIRE(writer.lift().size() > 0); + REQUIRE(writer.lift(lift_layer_id).size() > 0); AND_WHEN("Z is moved post-lift to the same delta as the config Z lift") { REQUIRE(writer.travel_to_z(trouble_Z + config.retract_lift.values[0]).size() == 0); AND_WHEN("GCodeWriter::Unlift() is called") { REQUIRE(writer.unlift().size() == 0); // we're the same height so no additional move happens. THEN("GCodeWriter::Lift() emits gcode.") { - REQUIRE(writer.lift().size() > 0); + REQUIRE(writer.lift(lift_layer_id).size() > 0); } } } @@ -81,13 +83,13 @@ SCENARIO("lift() is not ignored after unlift() at normal values of Z") { double trouble_Z{ 500003 }; writer.travel_to_z(trouble_Z); AND_WHEN("GcodeWriter::Lift() is called") { - REQUIRE(writer.lift().size() > 0); + REQUIRE(writer.lift(lift_layer_id).size() > 0); AND_WHEN("Z is moved post-lift to the same delta as the config Z lift") { REQUIRE(writer.travel_to_z(trouble_Z + config.retract_lift.values[0]).size() == 0); AND_WHEN("GCodeWriter::Unlift() is called") { REQUIRE(writer.unlift().size() == 0); // we're the same height so no additional move happens. THEN("GCodeWriter::Lift() emits gcode.") { - REQUIRE(writer.lift().size() > 0); + REQUIRE(writer.lift(lift_layer_id).size() > 0); } } } @@ -97,13 +99,13 @@ SCENARIO("lift() is not ignored after unlift() at normal values of Z") { double trouble_Z{ 10.3 }; writer.travel_to_z(trouble_Z); AND_WHEN("GcodeWriter::Lift() is called") { - REQUIRE(writer.lift().size() > 0); + REQUIRE(writer.lift(lift_layer_id).size() > 0); AND_WHEN("Z is moved post-lift to the same delta as the config Z lift") { REQUIRE(writer.travel_to_z(trouble_Z + config.retract_lift.values[0]).size() == 0); AND_WHEN("GCodeWriter::Unlift() is called") { REQUIRE(writer.unlift().size() == 0); // we're the same height so no additional move happens. THEN("GCodeWriter::Lift() emits gcode.") { - REQUIRE(writer.lift().size() > 0); + REQUIRE(writer.lift(lift_layer_id).size() > 0); } } } @@ -123,23 +125,23 @@ SCENARIO("set_speed emits values with fixed-point output.") { // } //} WHEN("set_speed is called to set speed to 9.99321e+04") { - THEN("Output string is G1 F99932.100") { - REQUIRE_THAT(writer.set_speed(9.99321e+04), Catch::Equals("G1 F10932.100\n")); + THEN("Output string is G1 F5995926") { + REQUIRE_THAT(writer.set_speed(9.99321e+04), Catch::Equals("G1 F5995926\n")); } } WHEN("set_speed is called to set speed to 1") { - THEN("Output string is G1 F1.000") { - REQUIRE_THAT(writer.set_speed(1.0), Catch::Equals("G1 F1.000\n")); + THEN("Output string is G1 F60") { + REQUIRE_THAT(writer.set_speed(1.0), Catch::Equals("G1 F60\n")); } } - WHEN("set_speed is called to set speed to 203.200022") { - THEN("Output string is G1 F203.200") { - REQUIRE_THAT(writer.set_speed(203.200022), Catch::Equals("G1 F203.200\n")); + WHEN("set_speed is called to set speed to 203.2000022") { + THEN("Output string is G1 F12192") { + REQUIRE_THAT(writer.set_speed(203.2000022), Catch::Equals("G1 F12192\n")); } } - WHEN("set_speed is called to set speed to 203.200522") { - THEN("Output string is G1 F203.200") { - REQUIRE_THAT(writer.set_speed(203.200522), Catch::Equals("G1 F203.201\n")); + WHEN("set_speed is called to set speed to 203.2000522") { + THEN("Output string is G1 F12192.003") { + REQUIRE_THAT(writer.set_speed(203.2000522), Catch::Equals("G1 F12192.003\n")); } } } diff --git a/tests/superslicerlibslic3r/test_geometry.cpp b/tests/superslicerlibslic3r/test_geometry.cpp index 0b19912ae31..5f02c918b84 100644 --- a/tests/superslicerlibslic3r/test_geometry.cpp +++ b/tests/superslicerlibslic3r/test_geometry.cpp @@ -1,7 +1,5 @@ -#define CATCH_CONFIG_DISABLE - -#include +#include #include #include @@ -15,7 +13,7 @@ using namespace Slic3r; TEST_CASE("Polygon::contains works properly", ""){ // this test was failing on Windows (GH #1950) - Polygon polygon{ Points{ + Slic3r::Polygon polygon( Points{ Point{207802834,-57084522}, Point{196528149,-37556190}, Point{173626821,-25420928}, @@ -26,7 +24,7 @@ TEST_CASE("Polygon::contains works properly", ""){ Point{82156517,-57084523}, Point{129714478,-84542120}, Point{160244873,-84542120} - } }; + } ); Point point{ 95706562, -57294774 }; REQUIRE(polygon.contains(point)); } @@ -43,8 +41,8 @@ SCENARIO("Intersections of line segments"){ } GIVEN("Scaled coordinates"){ - Line line1{ Point{73.6310778185108 / 0.0000001, 371.74239268924 / 0.0000001}, Point{73.6310778185108 / 0.0000001, 501.74239268924 / 0.0000001} }; - Line line2{ Point{75 / 0.0000001, 437.9853 / 0.0000001}, Point{62.7484 / 0.0000001, 440.4223 / 0.0000001} }; + Line line1{ Point::new_scale(73.6310778185108, 371.74239268924), Point::new_scale(73.6310778185108, 501.74239268924) }; + Line line2{ Point::new_scale(75, 437.9853), Point::new_scale(62.7484, 440.4223) }; THEN("There is still an intersection"){ Point point; REQUIRE(line1.intersection(line2,&point)); @@ -130,7 +128,7 @@ SCENARIO("polygon_is_convex works"){ TEST_CASE("Creating a polyline generates the obvious lines"){ - auto polyline = Polyline(); + auto polyline = Slic3r::Polyline(); polyline.points = std::vector({Point{0, 0}, Point{10, 0}, Point{20, 0}}); REQUIRE(polyline.lines().at(0).a == Point{0,0}); REQUIRE(polyline.lines().at(0).b == Point{10,0}); @@ -139,7 +137,7 @@ TEST_CASE("Creating a polyline generates the obvious lines"){ } TEST_CASE("Splitting a Polygon generates a polyline correctly"){ - auto polygon = Polygon(std::vector({Point{0, 0}, Point{10, 0}, Point{5, 5}})); + auto polygon = Slic3r::Polygon(std::vector({Point{0, 0}, Point{10, 0}, Point{5, 5}})); auto split = polygon.split_at_index(1); REQUIRE(split.points[0]==Point{10,0}); REQUIRE(split.points[1]==Point{5,5}); @@ -157,9 +155,9 @@ TEST_CASE("Bounding boxes are scaled appropriately"){ TEST_CASE("Offseting a line generates a polygon correctly"){ - Polyline tmp({ Point{10,10}, Point{20,10} }); - Polygon area = offset(tmp,5).at(0); - REQUIRE(area.area() == Polygon(std::vector({Point{10,5},Point{20,5},Point{20,15},Point{10,15}})).area()); + Slic3r::Polyline tmp(Points{{10,10},{20,10} }); + Slic3r::Polygon area = offset(tmp,5).at(0); + REQUIRE(area.area() == Slic3r::Polygon(std::vector({Point{10,5},Point{20,5},Point{20,15},Point{10,15}})).area()); } SCENARIO("Circle Fit, TaubinFit with Newton's method") { @@ -170,29 +168,29 @@ SCENARIO("Circle Fit, TaubinFit with Newton's method") { WHEN("Circle fit is called on the entire array") { Vec2d result_center(0,0); - result_center = Geometry::circle_taubin_newton(sample); + result_center = Geometry::circle_center_taubin_newton(sample); THEN("A center point of -6,0 is returned.") { - REQUIRE(result_center == expected_center); + REQUIRE((result_center - expected_center).norm() < EPSILON); } } WHEN("Circle fit is called on the first four points") { Vec2d result_center(0,0); - result_center = Geometry::circle_taubin_newton(sample.cbegin(), sample.cbegin()+4); + result_center = Geometry::circle_center_taubin_newton(sample.cbegin(), sample.cbegin()+4); THEN("A center point of -6,0 is returned.") { - REQUIRE(result_center == expected_center); + REQUIRE((result_center - expected_center).norm() < EPSILON); } } WHEN("Circle fit is called on the middle four points") { Vec2d result_center(0,0); - result_center = Geometry::circle_taubin_newton(sample.cbegin()+2, sample.cbegin()+6); + result_center = Geometry::circle_center_taubin_newton(sample.cbegin()+2, sample.cbegin()+6); THEN("A center point of -6,0 is returned.") { - REQUIRE(result_center == expected_center); + REQUIRE((result_center - expected_center).norm() < EPSILON); } } } GIVEN("A vector of Pointfs arranged in a half-circle with approximately the same distance R from some point") { Vec2d expected_center(-3, 9); - Pointfs sample {Vec2d{6.0, 0}, Vec2d{5.1961524, 3}, Vec2d{3 ,5.1961524}, + Vec2ds sample {Vec2d{6.0, 0}, Vec2d{5.1961524, 3}, Vec2d{3 ,5.1961524}, Vec2d{0, 6.0}, Vec2d{3, 5.1961524}, Vec2d{-5.1961524, 3}, Vec2d{-6.0, 0}}; @@ -201,23 +199,23 @@ SCENARIO("Circle Fit, TaubinFit with Newton's method") { WHEN("Circle fit is called on the entire array") { Vec2d result_center(0,0); - result_center = Geometry::circle_taubin_newton(sample); + result_center = Geometry::circle_center_taubin_newton(sample); THEN("A center point of 3,9 is returned.") { - REQUIRE(result_center == expected_center); + REQUIRE((result_center - expected_center).norm() < EPSILON); } } WHEN("Circle fit is called on the first four points") { Vec2d result_center(0,0); - result_center = Geometry::circle_taubin_newton(sample.cbegin(), sample.cbegin()+4); + result_center = Geometry::circle_center_taubin_newton(sample.cbegin(), sample.cbegin()+4); THEN("A center point of 3,9 is returned.") { - REQUIRE(result_center == expected_center); + REQUIRE((result_center - expected_center).norm() < EPSILON); } } WHEN("Circle fit is called on the middle four points") { Vec2d result_center(0,0); - result_center = Geometry::circle_taubin_newton(sample.cbegin()+2, sample.cbegin()+6); + result_center = Geometry::circle_center_taubin_newton(sample.cbegin()+2, sample.cbegin()+6); THEN("A center point of 3,9 is returned.") { - REQUIRE(result_center == expected_center); + REQUIRE((result_center - expected_center).norm() < EPSILON); } } } @@ -232,21 +230,21 @@ SCENARIO("Circle Fit, TaubinFit with Newton's method") { WHEN("Circle fit is called on the entire array") { Point result_center(0,0); - result_center = Geometry::circle_taubin_newton(sample); + result_center = Geometry::circle_center_taubin_newton(sample); THEN("A center point of scaled 3,9 is returned.") { REQUIRE(result_center.coincides_with_epsilon(expected_center)); } } WHEN("Circle fit is called on the first four points") { Point result_center(0,0); - result_center = Geometry::circle_taubin_newton(sample.cbegin(), sample.cbegin()+4); + result_center = Geometry::circle_center_taubin_newton(sample.cbegin(), sample.cbegin()+4); THEN("A center point of scaled 3,9 is returned.") { REQUIRE(result_center.coincides_with_epsilon(expected_center)); } } WHEN("Circle fit is called on the middle four points") { Point result_center(0,0); - result_center = Geometry::circle_taubin_newton(sample.cbegin()+2, sample.cbegin()+6); + result_center = Geometry::circle_center_taubin_newton(sample.cbegin()+2, sample.cbegin()+6); THEN("A center point of scaled 3,9 is returned.") { REQUIRE(result_center.coincides_with_epsilon(expected_center)); } @@ -285,7 +283,7 @@ SCENARIO("Line distances"){ SCENARIO("Polygon convex/concave detection"){ GIVEN(("A Square with dimension 100")){ - Polygon square/*new_scale*/{ std::vector{ + Slic3r::Polygon square/*new_scale*/{ std::vector{ Point{100,100}, Point{200,100}, Point{200,200}, @@ -301,7 +299,7 @@ SCENARIO("Polygon convex/concave detection"){ } } GIVEN("A Square with an extra colinearvertex"){ - Polygon square /*new_scale*/{ std::vector{ + Slic3r::Polygon square /*new_scale*/{ std::vector{ Point{150,100}, Point{200,100}, Point{200,200}, @@ -313,7 +311,7 @@ SCENARIO("Polygon convex/concave detection"){ } } GIVEN("A Square with an extra collinear vertex in different order"){ - Polygon square = Polygon /*new_scale*/{ std::vector{ + Slic3r::Polygon square /*new_scale*/{ std::vector{ Point{200,200}, Point{100,200}, Point{100,100}, @@ -326,7 +324,7 @@ SCENARIO("Polygon convex/concave detection"){ } GIVEN("A triangle"){ - Polygon triangle{ std::vector{ + Slic3r::Polygon triangle{ std::vector{ Point{16000170,26257364}, Point{714223,461012}, Point{31286371,461008} @@ -338,7 +336,7 @@ SCENARIO("Polygon convex/concave detection"){ } GIVEN("A triangle with an extra collinear point"){ - Polygon triangle{ std::vector{ + Slic3r::Polygon triangle{ std::vector{ Point{16000170,26257364}, Point{714223,461012}, Point{20000000,461012}, @@ -352,7 +350,7 @@ SCENARIO("Polygon convex/concave detection"){ GIVEN("A polygon with concave vertices with angles of specifically 4/3pi"){ // Two concave vertices of this polygon have angle = PI*4/3, so this test fails // if epsilon is not used. - Polygon polygon{ std::vector{ + Slic3r::Polygon polygon{ std::vector{ Point{60246458,14802768},Point{64477191,12360001}, Point{63727343,11060995},Point{64086449,10853608}, Point{66393722,14850069},Point{66034704,15057334}, @@ -370,7 +368,7 @@ SCENARIO("Polygon convex/concave detection"){ } TEST_CASE("Triangle Simplification does not result in less than 3 points"){ - Polygon triangle{ std::vector{ + Slic3r::Polygon triangle{ std::vector{ Point{16000170,26257364}, Point{714223,461012}, Point{31286371,461008} } }; REQUIRE(triangle.simplify(250000).at(0).points.size() == 3); diff --git a/tests/superslicerlibslic3r/test_model.cpp b/tests/superslicerlibslic3r/test_model.cpp index 98166fbf005..c6410b524ba 100644 --- a/tests/superslicerlibslic3r/test_model.cpp +++ b/tests/superslicerlibslic3r/test_model.cpp @@ -1,9 +1,12 @@ //#define CATCH_CONFIG_DISABLE - -#include +#include #include +#include #include +#include +#include +#include #include "test_data.hpp" // get access to init_print, etc using namespace Slic3r; @@ -13,12 +16,14 @@ SCENARIO("Model construction") { GIVEN("A Slic3r Model") { Model model{}; TriangleMesh sample_mesh = make_cube(20,20,20); - sample_mesh.repair(); + Slic3r::sla::IndexedMesh indexed_mesh(sample_mesh); // for ease of use + //sample_mesh.repair(); DynamicPrintConfig &config = Slic3r::DynamicPrintConfig::full_print_config(); Slic3r::Print print{}; print.apply(model, config); //Slic3r::Test::init_print(print, { sample_mesh }, model, config); + print.set_status_callback([](const PrintBase::SlicingStatus &) {}); WHEN("Model object is added") { ModelObject* mo = model.add_object(); @@ -35,13 +40,15 @@ SCENARIO("Model construction") { REQUIRE(mo->volumes.front()->is_modifier() == false); } THEN("Mesh is equivalent to input mesh.") { - TriangleMesh trimesh = mo->volumes.front()->mesh(); - REQUIRE(sample_mesh.vertices() == trimesh.vertices()); + Slic3r::sla::IndexedMesh trimesh(mo->volumes.front()->mesh()); + REQUIRE(indexed_mesh.vertices() == trimesh.vertices()); } ModelInstance* inst = mo->add_instance(); inst->set_rotation(Vec3d(0,0,0)); inst->set_scaling_factor(Vec3d(1, 1, 1)); - model.arrange_objects(print.config().min_object_distance()); + ArrangeParams params; + params.min_obj_distance = Slic3r::min_object_distance(print.config()); + Slic3r::arrange_objects(model, InfiniteBed{Point(scale_t(100),scale_t(100))}, params); model.center_instances_around_point(Slic3r::Vec2d(100,100)); print.auto_assign_extruders(mo); //print.add_model_object(mo); diff --git a/tests/superslicerlibslic3r/test_print.cpp b/tests/superslicerlibslic3r/test_print.cpp index 8528fb5d742..a0cef053e7c 100644 --- a/tests/superslicerlibslic3r/test_print.cpp +++ b/tests/superslicerlibslic3r/test_print.cpp @@ -1,13 +1,12 @@ //#define CATCH_CONFIG_DISABLE - -//#include -#include +#include #include "test_data.hpp" #include #include #include +#include //#include #include @@ -27,7 +26,7 @@ SCENARIO("PrintObject: Perimeter generation") { WHEN("make_perimeters() is called") { Print print{}; Slic3r::Test::init_print(print, { m }, model, &config); - PrintObject& object = *(print.objects().at(0)); + PrintObject& object = *print.objects_mutable().at(0); print.process(); // there are 66.66666.... layers for 0.3mm in 20mm //slic3r is rounded (slice at half-layer), slic3rPE is less? @@ -37,7 +36,7 @@ SCENARIO("PrintObject: Perimeter generation") { } THEN("Every layer in region 0 has 1 island of perimeters") { for(Layer* layer : object.layers()) { - REQUIRE(layer->regions()[0]->perimeters.entities.size() == 1); + REQUIRE(layer->regions()[0]->perimeters.entities().size() == 1); } } THEN("Every layer (but top) in region 0 has 3 paths in its perimeters list.") { @@ -67,13 +66,13 @@ SCENARIO("Print: Skirt generation") { print.process(); THEN("Skirt Extrusion collection has 2 loops in it") { REQUIRE(print.skirt().items_count() == 2); - REQUIRE(print.skirt().flatten().entities.size() == 2); + REQUIRE(print.skirt().flatten().entities().size() == 2); } } } } -void test_is_solid_infill(Print &p, size_t obj_id, size_t layer_id ) { +void test_is_solid_infill(Print &p, size_t obj_id, size_t layer_id, bool check = true ) { const PrintObject& obj { *(p.objects().at(obj_id)) }; const Layer& layer { *(obj.get_layer((int)layer_id)) }; @@ -81,7 +80,7 @@ void test_is_solid_infill(Print &p, size_t obj_id, size_t layer_id ) { for (const LayerRegion* reg : layer.regions()) { // for each region, iterate over the fill surfaces for (const Surface& su : reg->fill_surfaces.surfaces) { - CHECK(su.has_fill_solid()); + CHECK(su.has_fill_solid() == check); } } } @@ -94,6 +93,7 @@ SCENARIO("Print: Changing number of solid surfaces does not cause all surfaces t config.set_key_value("bottom_solid_layers", new ConfigOptionInt(1)); config.set_key_value("layer_height", new ConfigOptionFloat(0.5)); // get a known number of layers config.set_key_value("first_layer_height", new ConfigOptionFloatOrPercent(0.5, false)); + config.set_key_value("nozzle_diameter", new ConfigOptionFloats({1})); // has to be large enough for 0.5 layer height, the min/max lh depends on it config.set_key_value("enforce_full_fill_volume", new ConfigOptionBool(true)); Slic3r::Model model; auto event_counter {0U}; @@ -103,12 +103,26 @@ SCENARIO("Print: Changing number of solid surfaces does not cause all surfaces t print.process(); // Precondition: Ensure that the model has 2 solid top layers (39, 38) // and one solid bottom layer (0). - test_is_solid_infill(print, 0, 0); // should be solid - test_is_solid_infill(print, 0, 39); // should be solid - test_is_solid_infill(print, 0, 38); // should be solid + THEN("20 mm with 0.5 layer height means 40 layers.") + { + REQUIRE(print.objects().front()->layer_count() == 40); + } + THEN("First layer is solid bottom layer.") + { + test_is_solid_infill(print, 0, 0); // should be solid + test_is_solid_infill(print, 0, 1, false); // should not be solid + } + THEN("Two last layers are solid bottom layer.") + { + test_is_solid_infill(print, 0, 39); // should be solid + test_is_solid_infill(print, 0, 38); // should be solid + test_is_solid_infill(print, 0, 37, false); // should not be solid + } WHEN("Model is re-sliced with top_solid_layers == 3") { - ((ConfigOptionInt&)(print.regions()[0]->config().top_solid_layers)).value = 3; - print.invalidate_state_by_config_options(std::vector{ "posPrepareInfill" }); + ((ConfigOptionInt&)(print.get_print_region(0).config().top_solid_layers)).value = 3; + REQUIRE(print.get_print_region(0).config().top_solid_layers.value == 3); + DynamicPrintConfig useless; + print.invalidate_state_by_config_options(useless, std::vector{ "posPrepareInfill" }); print.process(); THEN("Print object does not have 0 solid bottom layers.") { test_is_solid_infill(print, 0, 0); @@ -160,8 +174,8 @@ SCENARIO("Print: Brim generation") { Print print{}; Slic3r::Test::init_print(print, { m }, model, &config); print.process(); - THEN("Brim Extrusion collection has 5 loops in it") { - REQUIRE(print.brim().items_count() == 5); + THEN("Brim Extrusion collection has 6 loops in it, even with offset") { + REQUIRE(print.brim().items_count() == 6); } } WHEN("Brim without first layer compensation") { @@ -170,25 +184,27 @@ SCENARIO("Print: Brim generation") { Print print{}; Slic3r::Test::init_print(print, { m }, model, &config); print.process(); - THEN("First Brim Extrusion has a length of ~88") { - REQUIRE(print.brim().entities.size() > 0); - double dist = unscaled(ExtrusionLength{}.length(*print.brim().entities.front())); - REQUIRE(dist > 22*4); - REQUIRE(dist < 22*4+1); + Flow brim_flow = print.brim_flow(0, print.default_object_config()); + THEN("First Brim Extrusion has a length of ~84") { + REQUIRE(print.brim().entities().size() > 0); + double dist = unscaled(ExtrusionLength{}.length(*print.brim().entities().front())); + REQUIRE(dist < (20 + brim_flow.spacing()) * 4 ); // little lower because of the round edge at the corners + REQUIRE(dist > (20 + brim_flow.spacing()) * 4 - 1); } } WHEN("Brim with 1mm first layer compensation") { config.set_key_value("brim_width", new ConfigOptionFloat(1)); config.set_key_value("brim_offset", new ConfigOptionFloat(0)); - config.set_key_value("first_layer_size_compensation", new ConfigOptionFloat(-1)); + config.set_key_value("first_layer_size_compensation", new ConfigOptionFloat(-0.5)); Print print{}; Slic3r::Test::init_print(print, { m }, model, &config); print.process(); + Flow brim_flow = print.brim_flow(0, print.objects().at(0)->config()); THEN("First Brim Extrusion has a length of ~80") { - REQUIRE(print.brim().entities.size() > 0); - double dist = unscaled(ExtrusionLength{}.length(*print.brim().entities.front())); - REQUIRE(dist > 20 * 4); - REQUIRE(dist < 20 * 4 + 1); + REQUIRE(print.brim().entities().size() > 0); + double dist = unscaled(ExtrusionLength{}.length(*print.brim().entities().front())); + REQUIRE(dist < (20 + brim_flow.spacing() - 1) * 4 );// little lower because of the round edge at the corners + REQUIRE(dist > (20 + brim_flow.spacing() - 1) * 4 - 1); } } WHEN("Brim is set to 6mm, extrusion width 0.5mm") { @@ -197,8 +213,10 @@ SCENARIO("Print: Brim generation") { Print print{}; Slic3r::Test::init_print(print, { m }, model, &config); print.process(); - double nbLoops = 6.0 / print.brim_flow(print.extruders().front()).spacing(); - THEN("Brim Extrusion collection has " + std::to_string(nbLoops) + " loops in it (flow="+ std::to_string(print.brim_flow(print.extruders().front()).spacing())+")") { + double nbLoops = 6.0 / print.brim_flow(*print.extruders().begin(), print.objects().at(0)->config()).spacing(); + THEN("Brim Extrusion collection has " + std::to_string(nbLoops) + " loops in it (flow=" + + std::to_string(print.brim_flow(*print.extruders().begin(), print.objects().at(0)->config()).spacing()) + ")") + { REQUIRE(print.brim().items_count() == floor(nbLoops)); } } @@ -215,40 +233,246 @@ SCENARIO("Print: Brim generation") { } } -SCENARIO("Print: perimeter generation") { - GIVEN("cube with hole, just enough space for two loops at a point") { - DynamicPrintConfig& config = Slic3r::DynamicPrintConfig::full_print_config(); - Slic3r::Model model{}; - config.set_key_value("first_layer_extrusion_width", new ConfigOptionFloatOrPercent(0.42, false)); - config.set_deserialize("nozzle_diameter", "0.4"); - config.set_deserialize("layer_height", "0.2"); - config.set_deserialize("first_layer_height", "0.2"); - config.set_key_value("only_one_perimeter_top", new ConfigOptionBool(false)); +struct GetFirst : ExtrusionVisitorRecursive +{ + ExtrusionLoop* first = nullptr; + ExtrusionLoop* previous_last = nullptr; + ExtrusionLoop* last = nullptr; + void default_use(ExtrusionEntity &entity) override { assert(false); }; + void use(ExtrusionLoop& loop) override { if(!first) first = &loop; previous_last = last; last = &loop; } +}; + +SCENARIO("Print: perimeter generation : cube with hole, just enough space for two loops at a point") +{ + DynamicPrintConfig &config = Slic3r::DynamicPrintConfig::full_print_config(); + Slic3r::Model model{}; + config.set_key_value("first_layer_extrusion_width", new ConfigOptionFloatOrPercent(0.42, false)); + config.set_deserialize("nozzle_diameter", "0.4"); + config.set_deserialize("layer_height", "0.2"); + config.set_deserialize("first_layer_height", "0.2"); + config.set_key_value("only_one_perimeter_top", new ConfigOptionBool(false)); + + auto facets = std::vector{Vec3i32(1, 4, 3), Vec3i32(4, 1, 2), Vec3i32(16, 12, 14), + Vec3i32(16, 10, 12), Vec3i32(10, 4, 6), Vec3i32(4, 10, 16), + Vec3i32(8, 14, 12), Vec3i32(8, 2, 14), Vec3i32(6, 2, 8), + Vec3i32(2, 6, 4), Vec3i32(14, 15, 16), Vec3i32(15, 14, 13), + Vec3i32(15, 4, 16), Vec3i32(4, 15, 3), Vec3i32(13, 11, 15), + Vec3i32(13, 7, 11), Vec3i32(7, 1, 5), Vec3i32(1, 7, 13), + Vec3i32(9, 15, 11), Vec3i32(9, 3, 15), Vec3i32(5, 3, 9), + Vec3i32(3, 5, 1), Vec3i32(1, 14, 2), Vec3i32(14, 1, 13), + Vec3i32(9, 12, 10), Vec3i32(12, 9, 11), Vec3i32(6, 9, 10), + Vec3i32(9, 6, 5), Vec3i32(8, 5, 6), Vec3i32(5, 8, 7), + Vec3i32(7, 12, 11), Vec3i32(12, 7, 8)}; + for (Vec3i32 &vec : facets) vec -= Vec3i32(1, 1, 1); + TriangleMesh tm = TriangleMesh{std::vector{Vec3f(-5, -5, -0.1), Vec3f(-5, -5, 0.1), Vec3f(-5, 5, -0.1), + Vec3f(-5, 5, 0.1), Vec3f(-1.328430, 0, -0.1), + Vec3f(-1.328430, 0, 0.1), Vec3f(1.5, -2.828430, -0.1), + Vec3f(1.5, -2.828430, 0.1), Vec3f(1.5, 2.828430, -0.1), + Vec3f(1.5, 2.828430, 0.1), Vec3f(4.328430, 0, -0.1), + Vec3f(4.328430, 0, 0.1), Vec3f(5, -5, -0.1), Vec3f(5, -5, 0.1), + Vec3f(5, 5, -0.1), Vec3f(5, 5, 0.1)}, + facets}; + + GIVEN("no brim") + { Print print{}; - auto facets = std::vector{ - Vec3i32(1,4,3),Vec3i32(4,1,2),Vec3i32(16,12,14),Vec3i32(16,10,12),Vec3i32(10,4,6),Vec3i32(4,10,16),Vec3i32(8,14,12),Vec3i32(8,2,14), - Vec3i32(6,2,8),Vec3i32(2,6,4),Vec3i32(14,15,16),Vec3i32(15,14,13),Vec3i32(15,4,16),Vec3i32(4,15,3),Vec3i32(13,11,15),Vec3i32(13,7,11), - Vec3i32(7,1,5),Vec3i32(1,7,13),Vec3i32(9,15,11),Vec3i32(9,3,15),Vec3i32(5,3,9),Vec3i32(3,5,1),Vec3i32(1,14,2),Vec3i32(14,1,13), - Vec3i32(9,12,10),Vec3i32(12,9,11),Vec3i32(6,9,10),Vec3i32(9,6,5),Vec3i32(8,5,6),Vec3i32(5,8,7),Vec3i32(7,12,11),Vec3i32(12,7,8) - }; - for (Vec3i32& vec : facets) - vec -= Vec3i32(1, 1, 1); - TriangleMesh tm = TriangleMesh{ std::vector{Vec3d(-5,-5,-0.1),Vec3d(-5,-5,0.1),Vec3d(-5,5,-0.1),Vec3d(-5,5,0.1), - Vec3d(-1.328430,0,-0.1),Vec3d(-1.328430,0,0.1),Vec3d(1.5,-2.828430,-0.1),Vec3d(1.5,-2.828430,0.1), - Vec3d(1.5,2.828430,-0.1),Vec3d(1.5,2.828430,0.1),Vec3d(4.328430,0,-0.1),Vec3d(4.328430,0,0.1), - Vec3d(5,-5,-0.1),Vec3d(5,-5,0.1),Vec3d(5,5,-0.1),Vec3d(5,5,0.1)}, - facets }; Slic3r::Test::init_print(print, {tm}, model, &config); print.process(); - THEN("hole perimeter should not be printed first") { - ExtrusionEntity* loop = print.objects()[0]->layers()[0]->regions()[0]->perimeters.entities[0]; - REQUIRE(loop->is_collection()); - loop = ((ExtrusionEntityCollection*)loop)->entities.front(); - REQUIRE(loop->is_loop()); - // what we don't want in first is something that is (((ExtrusionLoop*)loop)->loop_role() & ExtrusionLoopRole::elrHole) != 0 && loop->role() == elrExternalPerimeter - REQUIRE( (((ExtrusionLoop*)loop)->loop_role() & ExtrusionLoopRole::elrHole) == 0); + ExtrusionPrinter printer(/*mult=*/0.000001, /*trunc=*/100, /*json=*/true); + //std::cout << "\n\n\nNO BRIM EXTUSIONS:\n"; + //print.objects()[0]->layers()[0]->regions()[0]->perimeters.visit(printer); + //std::cout << "{" << printer.str() << "}"; + //Model model = print.model(); + //Slic3r::store_3mf("test_without_brim.3mf", &model, &print.full_print_config(), OptionStore3mf{}); + // see https://github.com/supermerill/SuperSlicer/issues/242, why the hole is after the contour inner + THEN("hole perimeter should not be printed first, but still before external one") + { + GetFirst get_first_visitor; + print.objects()[0]->layers()[0]->regions()[0]->perimeters.visit(get_first_visitor); + REQUIRE(get_first_visitor.first != nullptr); + REQUIRE(get_first_visitor.first->is_loop()); + // first inner contour peri + REQUIRE((get_first_visitor.first->loop_role() & ExtrusionLoopRole::elrHole) == 0); + REQUIRE(get_first_visitor.first->role() == ExtrusionRole::erPerimeter); + // the external hole perimeter (because it's alone without inner ones, we don't want it to be used as a skirt) + // note: here we may want to have the seam of this one near the next one instead of near our current pos, + // if it's an external one, to avoid oozing before external. + REQUIRE((get_first_visitor.previous_last->loop_role() & ExtrusionLoopRole::elrHole) != 0); + REQUIRE(get_first_visitor.previous_last->role() == ExtrusionRole::erExternalPerimeter); + // the external contour perimeter + REQUIRE((get_first_visitor.last->loop_role() & ExtrusionLoopRole::elrHole) == 0); + REQUIRE(get_first_visitor.last->role() == ExtrusionRole::erExternalPerimeter); + } + } + GIVEN("brim") + { + config.set_deserialize("brim_width", "0.2"); + Print print{}; + Slic3r::Test::init_print(print, {tm}, model, &config); + print.process(); + THEN("hole perimeter should not be printed first") + { + GetFirst get_first_visitor; + print.objects()[0]->layers()[0]->regions()[0]->perimeters.visit(get_first_visitor); + // the external contour perimeter + REQUIRE((get_first_visitor.first->loop_role() & ExtrusionLoopRole::elrHole) == 0); + REQUIRE(get_first_visitor.first->role() == ExtrusionRole::erExternalPerimeter); + // first inner contour peri + REQUIRE((get_first_visitor.previous_last->loop_role() & ExtrusionLoopRole::elrHole) == 0); + REQUIRE(get_first_visitor.previous_last->role() == ExtrusionRole::erPerimeter); + // the external hole perimeter + REQUIRE((get_first_visitor.last->loop_role() & ExtrusionLoopRole::elrHole) == ExtrusionLoopRole::elrHole); + REQUIRE(get_first_visitor.last->role() == ExtrusionRole::erExternalPerimeter); + } + } +} + +struct GetAll : ExtrusionVisitorRecursive +{ + std::vector loops; + void default_use(ExtrusionEntity &entity) override { assert(false); }; + void use(ExtrusionLoop& loop) override { loops.push_back(&loop); } +}; +SCENARIO("Print: perimeter generation : cube with hole in center") { + DynamicPrintConfig& config = Slic3r::DynamicPrintConfig::full_print_config(); + Slic3r::Model model{}; + config.set_key_value("first_layer_extrusion_width", new ConfigOptionFloatOrPercent(0.42, false)); + config.set_deserialize("nozzle_diameter", "0.4"); + config.set_deserialize("layer_height", "0.2"); + config.set_deserialize("first_layer_height", "0.2"); + config.set_key_value("only_one_perimeter_top", new ConfigOptionBool(false)); + + std::vector v{{-10, 10, -0.1}, {-10, -10, -0.1}, {-10, 10, 0.1}, {-10, -10, 0.1}, + {10, -10, -0.1}, {10, -10, 0.1}, {-2.5, 2.5, 0.1}, {-2.5, -2.5, 0.1}, + {2.5, -2.5, 0.1}, {10, 10, 0.1}, {2.5, 2.5, 0.1}, {10, 10, -0.1}, + {-2.5, 2.5, -0.1}, {-2.5, -2.5, -0.1}, {2.5, -2.5, -0.1}, {2.5, 2.5, -0.1}}; + std::vector i{{0, 1, 2}, {1, 3, 2}, {1, 4, 3}, {4, 5, 3}, {6, 2, 3}, {6, 3, 7}, + {5, 8, 7}, {5, 7, 3}, {9, 6, 10}, {9, 10, 8}, {9, 8, 5}, {9, 2, 6}, + {11, 0, 2}, {9, 11, 2}, {0, 12, 1}, {1, 12, 13}, {14, 4, 13}, {13, 4, 1}, + {12, 11, 15}, {15, 11, 14}, {14, 11, 4}, {0, 11, 12}, {4, 11, 9}, {5, 4, 9}, + {7, 13, 12}, {7, 12, 6}, {8, 14, 13}, {8, 13, 7}, {14, 8, 15}, {15, 8, 10}, + {15, 10, 12}, {12, 10, 6}}; + TriangleMesh tm = TriangleMesh(v, i); + + GIVEN("no brim") + { + config.set_deserialize("brim_width", "0"); + config.set_deserialize("brim_width_interior", "0"); + Print print{}; + Slic3r::Test::init_print(print, {tm}, model, &config); + print.process(); + // see https://github.com/supermerill/SuperSlicer/issues/242, why the hole is after the contour inner + GetAll get_all_visitor; + print.objects()[0]->layers()[0]->regions()[0]->perimeters.visit(get_all_visitor); + auto &loops = get_all_visitor.loops; + THEN("hole printed first, external last") + { + REQUIRE(loops.size() == 6); + // first holes + REQUIRE((loops[0]->loop_role() & ExtrusionLoopRole::elrHole) == ExtrusionLoopRole::elrHole); + REQUIRE(loops[0]->role() == ExtrusionRole::erPerimeter); + REQUIRE((loops[2]->loop_role() & ExtrusionLoopRole::elrHole) == ExtrusionLoopRole::elrHole); + REQUIRE(loops[2]->role() == ExtrusionRole::erExternalPerimeter); + } + THEN("contour printed last, external last") + { + //then contour + REQUIRE( (loops[3]->loop_role() & ExtrusionLoopRole::elrHole) == 0); + REQUIRE( loops[3]->role() == ExtrusionRole::erPerimeter); + REQUIRE( (loops[5]->loop_role() & ExtrusionLoopRole::elrHole) == 0); + REQUIRE( loops[5]->role() == ExtrusionRole::erExternalPerimeter); + } + } + GIVEN("contour brim") + { + config.set_deserialize("brim_width", "1"); + config.set_deserialize("brim_width_interior", "0"); + Print print{}; + Slic3r::Test::init_print(print, {tm}, model, &config); + print.process(); + ExtrusionPrinter printer(/*mult=*/0.000001, /*trunc=*/100, /*json=*/true); + GetAll get_all_visitor; + print.objects()[0]->layers()[0]->regions()[0]->perimeters.visit(get_all_visitor); + auto &loops = get_all_visitor.loops; + REQUIRE(loops.size() == 6); + THEN("contour printed first, external first") + { + //then contour + REQUIRE( (loops[0]->loop_role() & ExtrusionLoopRole::elrHole) == 0); + REQUIRE( loops[0]->role() == ExtrusionRole::erExternalPerimeter); + REQUIRE( (loops[2]->loop_role() & ExtrusionLoopRole::elrHole) == 0); + REQUIRE( loops[2]->role() == ExtrusionRole::erPerimeter); + } + THEN("hole printed last, external last as there is no hole brim") + { + // first holes + REQUIRE((loops[3]->loop_role() & ExtrusionLoopRole::elrHole) == ExtrusionLoopRole::elrHole); + REQUIRE(loops[3]->role() == ExtrusionRole::erPerimeter); + REQUIRE((loops[5]->loop_role() & ExtrusionLoopRole::elrHole) == ExtrusionLoopRole::elrHole); + REQUIRE(loops[5]->role() == ExtrusionRole::erExternalPerimeter); + } + //TODO: thinwall after evrything + } + GIVEN("hole brim") + { + config.set_deserialize("brim_width", "0"); + config.set_deserialize("brim_width_interior", "1"); + Print print{}; + Slic3r::Test::init_print(print, {tm}, model, &config); + print.process(); + ExtrusionPrinter printer(/*mult=*/0.000001, /*trunc=*/100, /*json=*/true); + GetAll get_all_visitor; + print.objects()[0]->layers()[0]->regions()[0]->perimeters.visit(get_all_visitor); + auto &loops = get_all_visitor.loops; + REQUIRE(loops.size() == 6); + THEN("hole printed first, external first") + { + // first holes + REQUIRE((loops[0]->loop_role() & ExtrusionLoopRole::elrHole) == ExtrusionLoopRole::elrHole); + REQUIRE(loops[0]->role() == ExtrusionRole::erExternalPerimeter); + REQUIRE((loops[2]->loop_role() & ExtrusionLoopRole::elrHole) == ExtrusionLoopRole::elrHole); + REQUIRE(loops[2]->role() == ExtrusionRole::erPerimeter); + } + THEN("contour printed last, external last") + { + //then contour + REQUIRE( (loops[3]->loop_role() & ExtrusionLoopRole::elrHole) == 0); + REQUIRE( loops[3]->role() == ExtrusionRole::erPerimeter); + REQUIRE( (loops[5]->loop_role() & ExtrusionLoopRole::elrHole) == 0); + REQUIRE( loops[5]->role() == ExtrusionRole::erExternalPerimeter); + } + //TODO: thinwall after evrything + } + GIVEN("both brim") + { + config.set_deserialize("brim_width", "1"); + config.set_deserialize("brim_width_interior", "1"); + Print print{}; + Slic3r::Test::init_print(print, {tm}, model, &config); + print.process(); + ExtrusionPrinter printer(/*mult=*/0.000001, /*trunc=*/100, /*json=*/true); + GetAll get_all_visitor; + print.objects()[0]->layers()[0]->regions()[0]->perimeters.visit(get_all_visitor); + auto &loops = get_all_visitor.loops; + REQUIRE(loops.size() == 6); + THEN("contour printed first, external first") + { + //then contour + REQUIRE( (loops[0]->loop_role() & ExtrusionLoopRole::elrHole) == 0); + REQUIRE( loops[0]->role() == ExtrusionRole::erExternalPerimeter); + REQUIRE( (loops[2]->loop_role() & ExtrusionLoopRole::elrHole) == 0); + REQUIRE( loops[2]->role() == ExtrusionRole::erPerimeter); + } + THEN("hole printed last, external first") + { + // first holes + REQUIRE((loops[3]->loop_role() & ExtrusionLoopRole::elrHole) == ExtrusionLoopRole::elrHole); + REQUIRE(loops[3]->role() == ExtrusionRole::erExternalPerimeter); + REQUIRE((loops[5]->loop_role() & ExtrusionLoopRole::elrHole) == ExtrusionLoopRole::elrHole); + REQUIRE(loops[5]->role() == ExtrusionRole::erPerimeter); } + //TODO: thinwall after evrything } } diff --git a/tests/superslicerlibslic3r/test_skirt_brim.cpp b/tests/superslicerlibslic3r/test_skirt_brim.cpp index aac1cf8b577..34f47adad53 100644 --- a/tests/superslicerlibslic3r/test_skirt_brim.cpp +++ b/tests/superslicerlibslic3r/test_skirt_brim.cpp @@ -1,13 +1,15 @@ //#define CATCH_CONFIG_DISABLE - -#include +#include #include "test_data.hpp" #include using namespace Slic3r::Test; using namespace Slic3r; +constexpr char* SKIRT_TAG = "Skirt"; +constexpr char* BRIM_TAG = "Brim"; + SCENARIO("skirt test by merill", "") { GIVEN("2 objects, don't complete individual object") { @@ -36,25 +38,25 @@ SCENARIO("skirt test by merill", "") { auto parser{ Slic3r::GCodeReader() }; parser.parse_file(gcode_filepath, [&layers_with_skirt, &layers_with_brim, &config](Slic3r::GCodeReader& self, const Slic3r::GCodeReader::GCodeLine& line) { - if (line.extruding(self) && line.comment().find("skirt") != std::string::npos) { + if (line.extruding(self) && line.comment().find(SKIRT_TAG) != std::string::npos) { layers_with_skirt[self.z()] = 1; } - if (line.extruding(self) && line.comment().find("brim") != std::string::npos) { + if (line.extruding(self) && line.comment().find(BRIM_TAG) != std::string::npos) { layers_with_brim[self.z()] = 1; } }); clean_file(gcode_filepath, "gcode"); THEN("one skrit generated") { - REQUIRE(print.skirt().entities.size() == 1); + REQUIRE(print.skirt().entities().size() == 1); for (auto obj : print.objects()) { - REQUIRE(obj->skirt().entities.size() == 0); + REQUIRE(obj->skirt().entities().size() == 0); } } THEN("brim is not generated") { - REQUIRE(print.brim().entities.size() == 0); + REQUIRE(print.brim().entities().size() == 0); for (auto obj : print.objects()) { - REQUIRE(obj->brim().entities.size() == 0); + REQUIRE(obj->brim().entities().size() == 0); } REQUIRE(layers_with_brim.size() == 0); } @@ -79,25 +81,25 @@ SCENARIO("skirt test by merill", "") { auto parser{ Slic3r::GCodeReader() }; parser.parse_file(gcode_filepath, [&layers_with_skirt, &layers_with_brim, &config](Slic3r::GCodeReader& self, const Slic3r::GCodeReader::GCodeLine& line) { - if (line.extruding(self) && line.comment().find("skirt") != std::string::npos) { + if (line.extruding(self) && line.comment().find(SKIRT_TAG) != std::string::npos) { layers_with_skirt[self.z()] = 1; } - if (line.extruding(self) && line.comment().find("brim") != std::string::npos) { + if (line.extruding(self) && line.comment().find(BRIM_TAG) != std::string::npos) { layers_with_brim[self.z()] = 1; } }); clean_file(gcode_filepath, "gcode"); THEN("one skirt generated") { - REQUIRE(print.skirt().entities.size() == 1); + REQUIRE(print.skirt().entities().size() == 1); for (auto obj : print.objects()) { - REQUIRE(obj->skirt().entities.size() == 0); + REQUIRE(obj->skirt().entities().size() == 0); } } THEN("brim generated") { - REQUIRE(print.brim().entities.size() > 0); + REQUIRE(print.brim().entities().size() > 0); for (auto obj : print.objects()) { - REQUIRE(obj->brim().entities.size() == 0); + REQUIRE(obj->brim().entities().size() == 0); } REQUIRE(layers_with_brim.size() == 1); } @@ -122,25 +124,25 @@ SCENARIO("skirt test by merill", "") { auto parser{ Slic3r::GCodeReader() }; parser.parse_file(gcode_filepath, [&layers_with_skirt, &layers_with_brim, &config](Slic3r::GCodeReader& self, const Slic3r::GCodeReader::GCodeLine& line) { - if (line.extruding(self) && line.comment().find("skirt") != std::string::npos) { + if (line.extruding(self) && line.comment().find(SKIRT_TAG) != std::string::npos) { layers_with_skirt[self.z()] = 1; } - if (line.extruding(self) && line.comment().find("brim") != std::string::npos) { + if (line.extruding(self) && line.comment().find(BRIM_TAG) != std::string::npos) { layers_with_brim[self.z()] = 1; } }); clean_file(gcode_filepath, "gcode"); THEN("no skirt generated") { - REQUIRE(print.skirt().entities.size() == 0); + REQUIRE(print.skirt().entities().size() == 0); for (auto obj : print.objects()) { - REQUIRE(obj->skirt().entities.size() == 0); + REQUIRE(obj->skirt().entities().size() == 0); } } THEN("brim generated") { - REQUIRE(print.brim().entities.size() > 0); + REQUIRE(print.brim().entities().size() > 0); for (auto obj : print.objects()) { - REQUIRE(obj->brim().entities.size() == 0); + REQUIRE(obj->brim().entities().size() == 0); } REQUIRE(layers_with_brim.size() == 1); } @@ -158,7 +160,8 @@ SCENARIO("skirt test by merill", "") { config.set_deserialize("fill_density", "0"); config.set_deserialize("perimeters", "1"); config.set_deserialize("complete_objects", "1"); - config.set_key_value("gcode_comments", new ConfigOptionBool(true)); + config.set_deserialize("brim_per_object", "1"); + config.set_deserialize("gcode_comments", "1"); WHEN("skirt with 3 layers is requested") { config.set_deserialize("skirts", "1"); @@ -176,23 +179,23 @@ SCENARIO("skirt test by merill", "") { auto parser{ Slic3r::GCodeReader() }; parser.parse_file(gcode_filepath, [&layers_with_skirt, &layers_with_brim, &config](Slic3r::GCodeReader& self, const Slic3r::GCodeReader::GCodeLine& line) { - if (line.extruding(self) && line.comment().find("skirt") != std::string::npos) { + if (line.extruding(self) && line.comment().find(SKIRT_TAG) != std::string::npos) { layers_with_skirt[self.z()] = 1; } - if (line.extruding(self) && line.comment().find("brim") != std::string::npos) { + if (line.extruding(self) && line.comment().find(BRIM_TAG) != std::string::npos) { layers_with_brim[self.z()] = 1; } }); THEN("one skirt per object") { - REQUIRE(print.skirt().entities.size() == 0); + REQUIRE(print.skirt().entities().size() == 0); for (auto obj : print.objects()) { - REQUIRE(obj->skirt().entities.size() == 1); + REQUIRE(obj->skirt().entities().size() == 1); } } THEN("brim is not generated") { - REQUIRE(print.brim().entities.size() == 0); + REQUIRE(print.brim().entities().size() == 0); for (auto obj : print.objects()) { - REQUIRE(obj->brim().entities.size() == 0); + REQUIRE(obj->brim().entities().size() == 0); } REQUIRE(layers_with_brim.size() == 0); } @@ -217,25 +220,25 @@ SCENARIO("skirt test by merill", "") { auto parser{ Slic3r::GCodeReader() }; parser.parse_file(gcode_filepath, [&layers_with_skirt, &layers_with_brim, &config](Slic3r::GCodeReader& self, const Slic3r::GCodeReader::GCodeLine& line) { - if (line.extruding(self) && line.comment().find("skirt") != std::string::npos) { + if (line.extruding(self) && line.comment().find(SKIRT_TAG) != std::string::npos) { layers_with_skirt[self.z()] = 1; } - if (line.extruding(self) && line.comment().find("brim") != std::string::npos) { + if (line.extruding(self) && line.comment().find(BRIM_TAG) != std::string::npos) { layers_with_brim[self.z()] = 1; } }); clean_file(gcode_filepath, "gcode"); THEN("one skirt per object") { - REQUIRE(print.skirt().entities.size() == 0); + REQUIRE(print.skirt().entities().size() == 0); for (auto obj : print.objects()) { - REQUIRE(obj->skirt().entities.size() == 1); + REQUIRE(obj->skirt().entities().size() == 1); } } THEN("brim generated") { - REQUIRE(print.brim().entities.size() == 0); + REQUIRE(print.brim().entities().size() == 0); for (auto obj : print.objects()) { - REQUIRE(obj->brim().entities.size() > 0); + REQUIRE(obj->brim().entities().size() > 0); } REQUIRE(layers_with_brim.size() == 1); } @@ -260,25 +263,25 @@ SCENARIO("skirt test by merill", "") { auto parser{ Slic3r::GCodeReader() }; parser.parse_file(gcode_filepath, [&layers_with_skirt, &layers_with_brim, &config](Slic3r::GCodeReader& self, const Slic3r::GCodeReader::GCodeLine& line) { - if (line.extruding(self) && line.comment().find("skirt") != std::string::npos) { + if (line.extruding(self) && line.comment().find(SKIRT_TAG) != std::string::npos) { layers_with_skirt[self.z()] = 1; } - if (line.extruding(self) && line.comment().find("brim") != std::string::npos) { + if (line.extruding(self) && line.comment().find(BRIM_TAG) != std::string::npos) { layers_with_brim[self.z()] = 1; } }); clean_file(gcode_filepath, "gcode"); THEN("no skrit") { - REQUIRE(print.skirt().entities.size() == 0); + REQUIRE(print.skirt().entities().size() == 0); for (auto obj : print.objects()) { - REQUIRE(obj->skirt().entities.size() == 0); + REQUIRE(obj->skirt().entities().size() == 0); } } THEN("brim generated") { - REQUIRE(print.brim().entities.size() == 0); + REQUIRE(print.brim().entities().size() == 0); for (auto obj : print.objects()) { - REQUIRE(obj->brim().entities.size() > 0); + REQUIRE(obj->brim().entities().size() > 0); } REQUIRE(layers_with_brim.size() == 1); } @@ -295,7 +298,7 @@ SCENARIO("Original Slic3r Skirt/Brim tests", "[!mayfail]") { config.set_deserialize("skirt_height", "2"); config.set_deserialize("perimeters", "1"); config.set_deserialize("support_material_speed", "99"); - config.set_key_value("gcode_comments", new ConfigOptionBool(true)); + config.set_deserialize("gcode_comments", "1"); // avoid altering speeds unexpectedly config.set_deserialize("cooling", "0"); @@ -312,7 +315,7 @@ SCENARIO("Original Slic3r Skirt/Brim tests", "[!mayfail]") { auto parser {Slic3r::GCodeReader()}; parser.parse_file(gcode_filepath, [&layers_with_skirt, &config] (Slic3r::GCodeReader& self, const Slic3r::GCodeReader::GCodeLine& line) { - if (line.extruding(self) && line.comment().find("skirt") != std::string::npos) { + if (line.extruding(self) && line.comment().find(SKIRT_TAG) != std::string::npos) { layers_with_skirt[self.z()] = 1; } //if (self.z() > 0) { @@ -350,7 +353,7 @@ SCENARIO("Original Slic3r Skirt/Brim tests", "[!mayfail]") { Print print{}; Slic3r::Test::init_print(print, { TestMesh::cube_20x20x20 }, model, &config, false); print.process(); - REQUIRE(print.brim().entities.size()>0); + REQUIRE(print.brim().entities().size()>0); } } diff --git a/tests/superslicerlibslic3r/test_thin.cpp b/tests/superslicerlibslic3r/test_thin.cpp index 53c26e59ab5..5e18d5c28ec 100644 --- a/tests/superslicerlibslic3r/test_thin.cpp +++ b/tests/superslicerlibslic3r/test_thin.cpp @@ -1,12 +1,12 @@ //#define CATCH_CONFIG_DISABLE - -#include +#include #include "test_data.hpp" #include -#include +#include #include #include +#include using namespace Slic3r; using namespace Slic3r::Geometry; @@ -16,7 +16,7 @@ class ExtrusionVolumeVisitor : public ExtrusionVisitorConst { double volume = 0; public: virtual void use(const ExtrusionPath &path) override { - for (int i = 0; i < path.polyline.size() - 1; i++) volume += path.polyline.points[i].distance_to(path.polyline.points[i + 1]) * path.mm3_per_mm; + for (int i = 0; i < path.polyline.size() - 1; i++) volume += unscaled(path.polyline.get_points()[i].distance_to(path.polyline.get_points()[i + 1])) * path.mm3_per_mm; }; virtual void use(const ExtrusionPath3D &path3D) override { std::cout << "error, not supported"; }; virtual void use(const ExtrusionMultiPath &multipath) override { @@ -27,7 +27,7 @@ class ExtrusionVolumeVisitor : public ExtrusionVisitorConst { for (const ExtrusionEntity &path : loop.paths) path.visit(*this); } virtual void use(const ExtrusionEntityCollection &collection) override { - for (const ExtrusionEntity *path : collection.entities) path->visit(*this); + for (const ExtrusionEntity *path : collection.entities()) path->visit(*this); } double compute(const ExtrusionEntity &entity) && { entity.visit(*this); @@ -46,10 +46,12 @@ SCENARIO("extrude_thinwalls") { Point::new_scale(-0.3, 10) } }; ThickPolylines res; - MedialAxis{ expolygon, scale_(1.1), scale_(0.5), scale_(0.2) }.build(res); - Flow periflow{ 1.1, 0.2, 0.4 }; - ExtrusionEntityCollection gap_fill = thin_variable_width(res, erGapFill, periflow); - + MedialAxis{ expolygon, scale_t(1.1), scale_t(0.5), scale_t(0.2) }.build(res); + Flow periflow = Flow::new_from_width(1.1f, 0.4f, 0.2f, 1.f, false); + ExtrusionEntityCollection gap_fill; + gap_fill.append(thin_variable_width(res, erGapFill, periflow, SCALED_EPSILON*2, true)); + + //Flow gapfill_max_flow = Flow::new_from_spacing(1.f, 0.4f, 0.2f, 1.f, false); //std::string gcode = gcodegen.get_visitor_gcode(); THEN("analyse extrusion.") { @@ -63,8 +65,6 @@ SCENARIO("extrude_thinwalls") { SCENARIO("thin walls: ") { - - GIVEN("Square") { Points test_set; @@ -160,13 +160,14 @@ SCENARIO("thin walls: ") } THEN("all medial axis segments of a semicircumference have the same orientation (but the 2 end points)") { Lines lines = res[0].lines(); - double min_angle = 1, max_angle = -1; + double min_angle = PI*4, max_angle = -PI*4; //std::cout << "first angle=" << lines[0].ccw(lines[1].b) << "\n"; for (int idx = 1; idx < lines.size() - 1; idx++) { - double angle = lines[idx - 1].ccw(lines[idx].b); + assert(lines[idx].a== lines[idx - 1].b); + double angle = lines[idx].a.ccw_angle(lines[idx - 1].a, lines[idx].b); if (std::abs(angle) - EPSILON < 0) angle = 0; //if (angle < 0) std::cout << unscale_(lines[idx - 1].a.x()) << ":" << unscale_(lines[idx - 1].a.y()) << " -> " << unscale_(lines[idx - 1].b.x()) << ":" << unscale_(lines[idx - 1].b.y()) << " -> " << unscale_(lines[idx].b.x()) << ":" << unscale_(lines[idx].b.y()) << "\n"; - std::cout << "angle=" << 180 * lines[idx].a.ccw_angle(lines[idx - 1].a, lines[idx].b) / PI << "\n"; + std::cout << "angle=" << 180*angle/PI << "\n"; min_angle = std::min(min_angle, angle); max_angle = std::max(max_angle, angle); } @@ -303,10 +304,10 @@ SCENARIO("thin walls: ") //} }; WHEN("1 nozzle, 0.2 layer height") { const coord_t nozzle_diam = scale_(1); - ExPolygon anchor = union_ex(ExPolygons{ tooth }, intersection_ex(ExPolygons{ base_part }, offset_ex(tooth, nozzle_diam / 2)), true)[0]; + ExPolygon anchor = union_ex(ExPolygons{ tooth }, intersection_ex(ExPolygons{ base_part }, offset_ex(tooth, nozzle_diam / 2)), ApplySafetyOffset::Yes)[0]; ThickPolylines res; //expolygon.medial_axis(scale_(1), scale_(0.5), &res); - Slic3r::MedialAxis ma(tooth, nozzle_diam * 2, nozzle_diam/3, scale_(0.2)); + Slic3r::Geometry::MedialAxis ma(tooth, /*min_width*/nozzle_diam * 2, /*max_width*/nozzle_diam/3, /*height*/scale_(0.2)); ma.use_bounds(anchor) .use_min_real_width(nozzle_diam) .use_tapers(0.25*nozzle_diam); @@ -319,16 +320,16 @@ SCENARIO("thin walls: ") } THEN("medial axis has the line width as max width") { double max_width = 0; - for (coordf_t width : res[0].width) max_width = std::max(max_width, width); + for (coordf_t width : res[0].points_width) max_width = std::max(max_width, width); REQUIRE(std::abs(max_width - scale_(1.2)) < SCALED_EPSILON); } //compute the length of the tapers THEN("medial axis has good tapers length") { int l1 = 0; - for (size_t idx = 0; idx < res[0].width.size() - 1 && res[0].width[idx] - nozzle_diam < SCALED_EPSILON; ++idx) + for (size_t idx = 0; idx < res[0].points_width.size() - 1 && res[0].points_width[idx] - nozzle_diam < SCALED_EPSILON; ++idx) l1 += res[0].lines()[idx].length(); int l2 = 0; - for (size_t idx = res[0].width.size() - 1; idx > 0 && res[0].width[idx] - nozzle_diam < SCALED_EPSILON; --idx) + for (size_t idx = res[0].points_width.size() - 1; idx > 0 && res[0].points_width[idx] - nozzle_diam < SCALED_EPSILON; --idx) l2 += res[0].lines()[idx - 1].length(); REQUIRE(std::abs(l1 - l2) < SCALED_EPSILON); REQUIRE(std::abs(l1 - scale_(0.25 - 0.1)) < SCALED_EPSILON); @@ -338,10 +339,10 @@ SCENARIO("thin walls: ") WHEN("1.2 nozzle, 0.6 layer height") { const coord_t nozzle_diam = scale_(1.2); - ExPolygon anchor = union_ex(ExPolygons{ tooth }, intersection_ex(ExPolygons{ base_part }, offset_ex(tooth, nozzle_diam / 4)), true)[0]; + ExPolygon anchor = union_ex(ExPolygons{ tooth }, intersection_ex(ExPolygons{ base_part }, offset_ex(tooth, nozzle_diam / 4)), ApplySafetyOffset::Yes)[0]; ThickPolylines res; //expolygon.medial_axis(scale_(1), scale_(0.5), &res); - Slic3r::MedialAxis ma(tooth, nozzle_diam * 2, nozzle_diam/3, scale_(0.6)); + Slic3r::Geometry::MedialAxis ma(tooth, /*min_width*/nozzle_diam * 2, /*max_width*/nozzle_diam/3, /*height*/scale_(0.6)); ma.use_bounds(anchor) .use_min_real_width(nozzle_diam) .use_tapers(1.0*nozzle_diam); @@ -354,24 +355,24 @@ SCENARIO("thin walls: ") } THEN("medial axis can'ty have a line width below Flow::new_from_spacing(nozzle_diam).width") { double max_width = 0; - for (coordf_t width : res[0].width) max_width = std::max(max_width, width); - double min_width = Flow::new_from_spacing(float(unscale_(nozzle_diam)), float(unscale_(nozzle_diam)), 0.6f, false).scaled_width(); + for (coordf_t width : res[0].points_width) max_width = std::max(max_width, width); + double min_width = Flow::new_from_spacing(float(unscaled(nozzle_diam)), float(unscaled(nozzle_diam)), 0.6f, 1.f, false).scaled_width(); REQUIRE(std::abs(max_width - min_width) < SCALED_EPSILON); REQUIRE(std::abs(max_width - nozzle_diam) > SCALED_EPSILON); } //compute the length of the tapers THEN("medial axis has a 45� taper and a shorter one") { - int l1 = 0; - for (size_t idx = 0; idx < res[0].width.size() - 1 && res[0].width[idx] - scale_(1.2) < SCALED_EPSILON; ++idx) - l1 += res[0].lines()[idx].length(); - int l2 = 0; - for (size_t idx = res[0].width.size() - 1; idx > 0 && res[0].width[idx] - scale_(1.2) < SCALED_EPSILON; --idx) - l2 += res[0].lines()[idx - 1].length(); + coord_t l1 = 0; + for (size_t idx = 0; idx < res[0].points_width.size() - 1 && res[0].points_width[idx] - scale_(1.2) < SCALED_EPSILON; ++idx) + l1 += coord_t(res[0].lines()[idx].length()); + coord_t l2 = 0; + for (size_t idx = res[0].points_width.size() - 1; idx > 0 && res[0].points_width[idx] - scale_(1.2) < SCALED_EPSILON; --idx) + l2 += coord_t(res[0].lines()[idx - 1].length()); //here the taper is limited by the 0-width spacing - double min_width = Flow::new_from_spacing(float(unscale_(nozzle_diam)), float(unscale_(nozzle_diam)), 0.6f, false).scaled_width(); + double min_width = Flow::new_from_spacing(float(unscaled(nozzle_diam)), float(unscaled(nozzle_diam)), 0.6f, 1.f, false).scaled_width(); REQUIRE(std::abs(l1 - l2) < SCALED_EPSILON); - REQUIRE(l1 < scale_(0.6)); - REQUIRE(l1 > scale_(0.4)); + REQUIRE(l1 < scale_t(0.6)); + REQUIRE(l1 > scale_t(0.4)); } } } From 3c18474a9ae50266ceea21071805ba63021e91e2 Mon Sep 17 00:00:00 2001 From: supermerill Date: Wed, 10 Jan 2024 18:17:53 +0100 Subject: [PATCH 09/25] FIx 0 acceleration for reprap supermerill/SuperSlicer#4048 --- src/libslic3r/GCodeWriter.cpp | 27 +++++++++++++++++-------- src/libslic3r/GCodeWriter.hpp | 38 +++++++++++++++-------------------- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/src/libslic3r/GCodeWriter.cpp b/src/libslic3r/GCodeWriter.cpp index b538b58fcc9..d3ac685faac 100644 --- a/src/libslic3r/GCodeWriter.cpp +++ b/src/libslic3r/GCodeWriter.cpp @@ -311,23 +311,34 @@ std::string GCodeWriter::write_acceleration(){ //try to set only printing acceleration, travel should be untouched if possible if (FLAVOR_IS(gcfRepetier)) { // M201: Set max printing acceleration - gcode << "M201 X" << m_current_acceleration << " Y" << m_current_acceleration; + if (m_current_acceleration > 0) + gcode << "M201 X" << m_current_acceleration << " Y" << m_current_acceleration; } else if(FLAVOR_IS(gcfLerdge) || FLAVOR_IS(gcfSprinter)){ // M204: Set printing acceleration // This is new MarlinFirmware with separated print/retraction/travel acceleration. // Use M204 P, we don't want to override travel acc by M204 S (which is deprecated anyway). - gcode << "M204 P" << m_current_acceleration; + if (m_current_acceleration > 0) + gcode << "M204 P" << m_current_acceleration; } else if (FLAVOR_IS(gcfMarlinFirmware) || FLAVOR_IS(gcfRepRap)) { // M204: Set printing & travel acceleration - gcode << "M204 P" << m_current_acceleration << " T" << (m_current_travel_acceleration > 0 ? m_current_travel_acceleration : m_current_acceleration); + if (m_current_acceleration > 0) + gcode << "M204 P" << m_current_acceleration << " T" << (m_current_travel_acceleration > 0 ? m_current_travel_acceleration : m_current_acceleration); + else if(m_current_travel_acceleration > 0) + gcode << "M204 T" << m_current_travel_acceleration; } else { // gcfMarlinLegacy // M204: Set default acceleration - gcode << "M204 S" << m_current_acceleration; + if (m_current_acceleration > 0) + gcode << "M204 S" << m_current_acceleration; } - if (this->config.gcode_comments) gcode << " ; adjust acceleration"; - gcode << "\n"; - - return gcode.str(); + //if at least something, add comment and line return + if (gcode.tellp() != std::streampos(0)) { + if (this->config.gcode_comments) + gcode << " ; adjust acceleration"; + gcode << "\n"; + return gcode.str(); + } + assert(gcode.str().empty()); + return ""; } std::string GCodeWriter::reset_e(bool force) diff --git a/src/libslic3r/GCodeWriter.hpp b/src/libslic3r/GCodeWriter.hpp index 85735706a76..352dbe4fd3c 100644 --- a/src/libslic3r/GCodeWriter.hpp +++ b/src/libslic3r/GCodeWriter.hpp @@ -17,13 +17,7 @@ class GCodeWriter { // override from region const PrintRegionConfig* config_region = nullptr; - GCodeWriter() : - multiple_extruders(false), m_extrusion_axis("E"), m_tool(nullptr), - m_single_extruder_multi_material(false), - m_last_acceleration(0), m_current_acceleration(0), m_current_speed(0), - m_last_bed_temperature(0), m_last_bed_temperature_reached(true), - m_lifted(0) - {} + GCodeWriter() {} Tool* tool() { return m_tool; } const Tool* tool() const { return m_tool; } @@ -96,25 +90,25 @@ class GCodeWriter { // Extruders are sorted by their ID, so that binary search is possible. std::vector m_extruders; std::vector m_millers; - std::string m_extrusion_axis; - bool m_single_extruder_multi_material; - Tool* m_tool; - uint32_t m_last_acceleration; - uint32_t m_last_travel_acceleration; - uint32_t m_current_acceleration; - uint32_t m_current_travel_acceleration; - double m_current_speed; - uint8_t m_last_fan_speed; - int16_t m_last_temperature; - int16_t m_last_temperature_with_offset; - int16_t m_last_bed_temperature; - bool m_last_bed_temperature_reached; + std::string m_extrusion_axis = "E"; + bool m_single_extruder_multi_material = false; + Tool* m_tool = nullptr; + uint32_t m_last_acceleration = 0; + uint32_t m_last_travel_acceleration = 0; + uint32_t m_current_acceleration = 0; + uint32_t m_current_travel_acceleration = 0; + double m_current_speed = 0; + uint8_t m_last_fan_speed = 0; + int16_t m_last_temperature = 0; + int16_t m_last_temperature_with_offset = 0; + int16_t m_last_bed_temperature = 0; + bool m_last_bed_temperature_reached = true; // if positive, it's set, and the next lift wil have this extra lift double m_extra_lift = 0; // current lift, to remove from m_pos to have the current height. - double m_lifted; + double m_lifted = 0; Vec3d m_pos = Vec3d::Zero(); - + std::string _travel_to_z(double z, const std::string &comment); std::string _retract(double length, std::optional restart_extra, std::optional restart_extra_toolchange, const std::string &comment); From b74f5d95974a4933080ff3c7c995af03335782e9 Mon Sep 17 00:00:00 2001 From: supermerill Date: Thu, 11 Jan 2024 13:38:29 +0100 Subject: [PATCH 10/25] Fix Seam gap in filament section keep reactivating supermerill/superslicer#4065 --- src/libslic3r/Config.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp index db381393d4a..2bf58d706dd 100644 --- a/src/libslic3r/Config.hpp +++ b/src/libslic3r/Config.hpp @@ -1326,7 +1326,7 @@ class ConfigOptionFloatsOrPercentsTempl : public ConfigOptionVectorvalues) - if (! std::isnan(v.value) || v != NIL_VALUE()) + if (!std::isnan(v.value) && v != NIL_VALUE()) return false; return true; } else { From 4ef70b704a483f78a3fd3109c995e7df82809f71 Mon Sep 17 00:00:00 2001 From: supermerill Date: Sat, 13 Jan 2024 01:03:45 +0100 Subject: [PATCH 11/25] safer nil for float&percent --- src/libslic3r/Config.hpp | 16 +++++++++------- src/slic3r/GUI/SavePresetDialog.cpp | 2 +- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp index 2bf58d706dd..c9e4e7536d6 100644 --- a/src/libslic3r/Config.hpp +++ b/src/libslic3r/Config.hpp @@ -1326,7 +1326,7 @@ class ConfigOptionFloatsOrPercentsTempl : public ConfigOptionVectorvalues) - if (!std::isnan(v.value) && v != NIL_VALUE()) + if (!(std::isnan(v.value) || v.value == NIL_VALUE().value || v.value > std::numeric_limits::max())) return false; return true; } else { @@ -1344,7 +1344,9 @@ class ConfigOptionFloatsOrPercentsTempl : public ConfigOptionVector(to_check).value) || boost::any_cast(to_check).value == NIL_VALUE().value; + bool ok = std::isnan(boost::any_cast(to_check).value) || boost::any_cast(to_check).value == NIL_VALUE().value + || boost::any_cast(to_check).value > std::numeric_limits::max(); + return ok; } // don't use it to compare, use is_nil() to check. static inline boost::any create_nil() { return boost::any(NIL_VALUE()); } @@ -1411,7 +1413,7 @@ class ConfigOptionFloatsOrPercentsTempl : public ConfigOptionVector std::numeric_limits::max()) { if (NULLABLE) ss << NIL_STR_VALUE; else @@ -1424,8 +1426,8 @@ class ConfigOptionFloatsOrPercentsTempl : public ConfigOptionVectorvalue) || it1->value == NIL_VALUE().value) && - (std::isnan(it2->value) || it2->value == NIL_VALUE().value)) || + if (!(((std::isnan(it1->value) || it1->value == NIL_VALUE().value || it1->value > std::numeric_limits::max()) && + (std::isnan(it2->value) || it2->value == NIL_VALUE().value || it1->value > std::numeric_limits::max())) || *it1 == *it2)) return false; return true; @@ -1436,8 +1438,8 @@ class ConfigOptionFloatsOrPercentsTempl : public ConfigOptionVector &v1, const std::vector &v2) { if (NULLABLE) { for (auto it1 = v1.begin(), it2 = v2.begin(); it1 != v1.end() && it2 != v2.end(); ++ it1, ++ it2) { - auto null1 = int(std::isnan(it1->value) || it1->value == NIL_VALUE().value); - auto null2 = int(std::isnan(it2->value) || it2->value == NIL_VALUE().value); + auto null1 = int(std::isnan(it1->value) || it1->value == NIL_VALUE().value || it1->value > std::numeric_limits::max()); + auto null2 = int(std::isnan(it2->value) || it2->value == NIL_VALUE().value || it1->value > std::numeric_limits::max()); return (null1 < null2) || (null1 == null2 && *it1 < *it2); } return v1.size() < v2.size(); diff --git a/src/slic3r/GUI/SavePresetDialog.cpp b/src/slic3r/GUI/SavePresetDialog.cpp index 59418c3f89c..3f30d8e8715 100644 --- a/src/slic3r/GUI/SavePresetDialog.cpp +++ b/src/slic3r/GUI/SavePresetDialog.cpp @@ -124,7 +124,7 @@ void SavePresetDialog::Item::update() } if (m_valid_type == Valid && existing && (existing->is_external)) { - info_line = _L("Cannot overwrite an external profile."); + info_line = _L("Cannot overwrite an external profile. Please choose another name."); m_valid_type = NoValid; } From 21c6e04cc040472507949da79f4b6f7a9cffc1f2 Mon Sep 17 00:00:00 2001 From: supermerill Date: Mon, 15 Jan 2024 11:12:51 +0100 Subject: [PATCH 12/25] fix parsing utf-8 for not-alphanumeric chars supermerill/SuperSlicer#4070 --- src/libslic3r/GCode.cpp | 49 ++++++++++++++++++++++++----------------- src/libslic3r/GCode.hpp | 1 + 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index bba0eb5b915..ce20991b3a2 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -32,7 +32,6 @@ #include #include #include -#include #include #include @@ -1426,6 +1425,7 @@ void GCode::_do_export(Print& print_mod, GCodeOutputStream &file, ThumbnailsGene } BoundingBoxf3 global_bounding_box; size_t nb_items = 0; + std::wregex pattern(L"[^\\w]+", std::regex_constants::ECMAScript); for (PrintObject *print_object : print.objects()) { this->m_ordered_objects.push_back(print_object); uint32_t copy_id = 0; @@ -1471,9 +1471,14 @@ void GCode::_do_export(Print& print_mod, GCodeOutputStream &file, ThumbnailsGene for (const Point& point : poly.points) s_poly += (boost::format(format_point) % unscaled(point.x()) % unscaled(point.y())).str() + ","; s_poly += (boost::format(format_point) % unscaled(poly.points.front().x()) % unscaled(poly.points.front().y())).str(); - + //std::string good_name_without_space = boost::algorithm::replace_all_regex(print_object->model_object()->name, regex_space, std::string("_")); + //std::locale::global(std::locale("en_US.UTF-8")); + std::wstring wname = boost::nowide::widen(print_object->model_object()->name); + std::wstring wname_without_space = std::regex_replace(wname, pattern, L"_"); + std::string name_without_space = boost::nowide::narrow(wname_without_space); + raw_str_to_objectid_str[print_object->model_object()->name] = name_without_space; file.write_format("EXCLUDE_OBJECT_DEFINE NAME=%s_id_%d_copy_%d CENTER=%f,%f POLYGON=[%s]\n", - boost::algorithm::replace_all_regex_copy(print_object->model_object()->name, boost::regex("[^\\w]+"), std::string("_")).c_str(), + name_without_space.c_str(), this->m_ordered_objects.size() - 1, copy_id, bounding_box.center().x(), bounding_box.center().y(), s_poly.c_str() @@ -2836,7 +2841,7 @@ namespace Skirt { } // namespace Skirt // Matches "G92 E0" with various forms of writing the zero and with an optional comment. -boost::regex regex_g92e0_gcode{ "^[ \\t]*[gG]92[ \\t]*[eE](0(\\.0*)?|\\.0+)[ \\t]*(;.*)?$" }; +std::regex regex_g92e0_gcode{ "^[ \\t]*[gG]92[ \\t]*[eE](0(\\.0*)?|\\.0+)[ \\t]*(;.*)?$" }; // In sequential mode, process_layer is called once per each object and its copy, // therefore layers will contain a single entry and single_object_instance_idx will point to the copy of the object. @@ -2978,8 +2983,8 @@ LayerResult GCode::process_layer( } //put G92 E0 is relative extrusion - bool before_layer_gcode_resets_extruder = boost::regex_search(print.config().before_layer_gcode.value, regex_g92e0_gcode); - bool layer_gcode_resets_extruder = boost::regex_search(print.config().layer_gcode.value, regex_g92e0_gcode); + bool before_layer_gcode_resets_extruder = std::regex_search(print.config().before_layer_gcode.value, regex_g92e0_gcode); + bool layer_gcode_resets_extruder = std::regex_search(print.config().layer_gcode.value, regex_g92e0_gcode); if (m_config.use_relative_e_distances) { // See GH issues prusa#6336 #5073$ if (!before_layer_gcode_resets_extruder && !layer_gcode_resets_extruder) { @@ -3306,20 +3311,12 @@ LayerResult GCode::process_layer( bool object_layer_over_raft = layer_to_print.object_layer && layer_to_print.object_layer->id() > 0 && instance_to_print.print_object.slicing_parameters().raft_layers() == layer_to_print.object_layer->id(); // Get data for gcode_label_objects - std::string instance_clean_name = - boost::algorithm::replace_all_regex_copy( - instance_to_print.print_object.model_object()->name, - boost::regex("[^\\w]+"), std::string("_")); - std::string instance_id = std::to_string( - std::find(this->m_ordered_objects.begin(), - this->m_ordered_objects.end(), - &instance_to_print.print_object) - - this->m_ordered_objects.begin()); - std::string instance_copy = std::to_string( - instance_to_print.instance_id); - std::string instance_full_id = instance_clean_name + "_id_" + - instance_id + "_copy_" + - instance_copy; + std::string instance_id = std::to_string(std::find(this->m_ordered_objects.begin(), + this->m_ordered_objects.end(), + &instance_to_print.print_object) - + this->m_ordered_objects.begin()); + std::string instance_copy = std::to_string(instance_to_print.instance_id); + std::string instance_full_id; // for klipper m_layer = layer_to_print.layer(); m_object_layer_over_raft = object_layer_over_raft; @@ -3344,6 +3341,17 @@ LayerResult GCode::process_layer( instance_plater_id += instance_to_print.instance_id; m_gcode_label_objects_start += std::string("M486 S") + std::to_string(instance_plater_id) + "\n"; } else if (print.config().gcode_flavor.value == gcfKlipper) { + std::string instance_clean_name; + if (auto found = raw_str_to_objectid_str.find( + instance_to_print.print_object.model_object()->name); + found != raw_str_to_objectid_str.end()) { + instance_clean_name = found->second; + } else { + assert(false); // should already been done in EXCLUDE_OBJECT_DEFINE + instance_clean_name = instance_to_print.print_object.model_object()->name; + } + instance_full_id = instance_clean_name + "_id_" + instance_id + "_copy_" + + instance_copy; m_gcode_label_objects_start += std::string("EXCLUDE_OBJECT_START NAME=") + instance_full_id + @@ -3430,6 +3438,7 @@ LayerResult GCode::process_layer( m_gcode_label_objects_end += std::string("M486 S-1") + "\n"; } else if (print.config().gcode_flavor.value == gcfKlipper) { + assert(!instance_full_id.empty()); m_gcode_label_objects_end += std::string("EXCLUDE_OBJECT_END NAME=") + instance_full_id + diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index 89653e6363c..5a42e0bfe87 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -491,6 +491,7 @@ class GCode : ExtrusionVisitorConst { std::string m_gcode_label_objects_start; std::string m_gcode_label_objects_end; void _add_object_change_labels(std::string &gcode); + std::map raw_str_to_objectid_str; bool m_silent_time_estimator_enabled; From 97f88599cace1a1a4fb58437fcfed645edbb64a9 Mon Sep 17 00:00:00 2001 From: supermerill Date: Mon, 15 Jan 2024 16:33:48 +0100 Subject: [PATCH 13/25] more assert verification & small fixes --- src/libslic3r/Arachne/utils/ExtrusionLine.hpp | 4 + src/libslic3r/GCode/SeamPlacer.cpp | 27 ++- src/libslic3r/PerimeterGenerator.cpp | 195 +++++++++++++++--- 3 files changed, 190 insertions(+), 36 deletions(-) diff --git a/src/libslic3r/Arachne/utils/ExtrusionLine.hpp b/src/libslic3r/Arachne/utils/ExtrusionLine.hpp index 638d7f237f8..0b13859e207 100644 --- a/src/libslic3r/Arachne/utils/ExtrusionLine.hpp +++ b/src/libslic3r/Arachne/utils/ExtrusionLine.hpp @@ -224,6 +224,10 @@ static inline Slic3r::ThickPolyline to_thick_polyline(const ClipperLib_Z::Path & out.points_width.emplace_back(it->z()); } } + assert(out.points.front().x() == path.front().x()); + assert(out.points.front().y() == path.front().y()); + assert(out.points.back().x() == path.back().x()); + assert(out.points.back().y() == path.back().y()); return out; } diff --git a/src/libslic3r/GCode/SeamPlacer.cpp b/src/libslic3r/GCode/SeamPlacer.cpp index 765b60be632..e050289a083 100644 --- a/src/libslic3r/GCode/SeamPlacer.cpp +++ b/src/libslic3r/GCode/SeamPlacer.cpp @@ -431,6 +431,7 @@ Polygons extract_perimeter_polygons(const Layer *layer, const SeamPosition confi const LayerRegion* current_layer_region; SeamPosition configured_seam_preference; public: + bool also_overhangs = false; PerimeterCopy(std::vector* regions_out, Polygons* polys, SeamPosition configured_seam) : corresponding_regions_out(regions_out), configured_seam_preference(configured_seam), polygons(polys) { } @@ -441,9 +442,13 @@ Polygons extract_perimeter_polygons(const Layer *layer, const SeamPosition confi if (path.role() == ExtrusionRole::erExternalPerimeter) { role = ExtrusionRole::erExternalPerimeter; } + if (path.role() == ExtrusionRole::erOverhangPerimeter && + also_overhangs) { // TODO find a way to search for external overhangs only + role = ExtrusionRole::erOverhangPerimeter; + } } - if (role == ExtrusionRole::erExternalPerimeter + if (role == ExtrusionRole::erExternalPerimeter || (role == ExtrusionRole::erOverhangPerimeter && also_overhangs) || (is_perimeter(role) && configured_seam_preference == spAllRandom)) { //for random seam alignment, extract all perimeters Points p; loop.collect_points(p); @@ -464,12 +469,20 @@ Polygons extract_perimeter_polygons(const Layer *layer, const SeamPosition confi visitor.set_current_layer_region(layer_region); ex_entity->visit(visitor); if (polygons.empty()) { - Points p; - ex_entity->collect_points(p); - polygons.emplace_back(std::move(p)); - corresponding_regions_out.push_back(layer_region); - //shouldn't happen - assert(false); + //can happen if the external is fully an overhang + visitor.also_overhangs = true; + ex_entity->visit(visitor); + visitor.also_overhangs = false; + if (polygons.empty()) { + //shouldn't happen + ex_entity->visit(visitor); + assert(false); + // what to do in this case? + Points p; + ex_entity->collect_points(p); + polygons.emplace_back(std::move(p)); + corresponding_regions_out.push_back(layer_region); + } } } } diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index 5b598e0e015..d3f01c621f4 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -2088,6 +2088,60 @@ ExtrusionPaths PerimeterGenerator::create_overhangs(const Polyline& loop_polygon return paths; } +#ifdef _DEBUG +void test_overhangs(const std::vector& path1, const std::vector& path2, Points &outer_points) +{ + for (const ClipperLib_Z::Path &poly : path1) + for (int i = 0; i < poly.size() - 1; i++) + assert(poly[i] != poly[i + 1]); + for (const ClipperLib_Z::Path &poly : path2) + for (int i = 0; i < poly.size() - 1; i++) + assert(poly[i] != poly[i + 1]); + // check if points are equal + //Points path2_points; + //Points path1_points; + //for (auto &line : path2) + // for (auto &pt : line) path2_points.emplace_back(coord_t(pt.x()), coord_t(pt.y())); + //for (auto &line : path1) + // for (auto &pt : line) path1_points.emplace_back(coord_t(pt.x()), coord_t(pt.y())); + //for (Point &pt : path2_points) { + // bool found = false; + // bool in_outer = false; + // Point pt2_almost; + // for (Point &pt2 : path1_points) + // if (pt.coincides_with_epsilon(pt2)) { + // found = true; + // pt2_almost = pt2; + // break; + // } + // for (Point &pt2 : outer_points) + // if (pt.coincides_with_epsilon(pt2)) { + // found = true; + // in_outer = true; + // pt2_almost = pt2; + // break; + // } + // assert(found); + // found = false; + // in_outer = false; + // for (Point &pt2 : path1_points) + // if (pt.coincides_with(pt2)) { + // found = true; + // break; + // } + // for (Point &pt2 : outer_points) + // if (pt.coincides_with(pt2)) { + // found = true; + // in_outer = true; + // break; + // } + // assert(found); + //} + // => points can be different from diff & intersect + // TODO: create a new operation that create the diff & intersect at the same time +} +#endif + //TODO: transform to ExtrusionMultiPath instead of ExtrusionPaths ExtrusionPaths PerimeterGenerator::create_overhangs(const ClipperLib_Z::Path& arachne_path, ExtrusionRole role, bool is_external) const { ExtrusionPaths paths; @@ -2130,6 +2184,10 @@ ExtrusionPaths PerimeterGenerator::create_overhangs(const ClipperLib_Z::Path& ar if (overhangs_width_speed > 0 && (overhangs_width_speed < overhangs_width || overhangs_width == 0)) { if (!this->_lower_slices_bridge_speed_small_clipperpaths.empty()) { //small_speed = diff_pl(*previous, this->_lower_slices_bridge_speed_small); +#ifdef _DEBUG + Points outer_points; + for(auto & line: *previous) for(auto &pt : line) outer_points.emplace_back(coord_t(pt.x()), coord_t(pt.y())); +#endif small_speed = clip_extrusion(*previous, this->_lower_slices_bridge_speed_small_clipperpaths, ClipperLib_Z::ctDifference); #ifdef _DEBUG for (ClipperLib_Z::Path& poly : small_speed) // assert small_speed @@ -2139,14 +2197,17 @@ ExtrusionPaths PerimeterGenerator::create_overhangs(const ClipperLib_Z::Path& ar if (!small_speed.empty()) { *previous = clip_extrusion(*previous, this->_lower_slices_bridge_speed_small_clipperpaths, ClipperLib_Z::ctIntersection); #ifdef _DEBUG - for (ClipperLib_Z::Path& poly : *previous) // assert previous - for (int i = 0; i < poly.size() - 1; i++) // assert previous - assert(poly[i] != poly[i + 1]); // assert previous + test_overhangs(small_speed, *previous, outer_points); + test_overhangs(*previous, small_speed, outer_points); #endif previous = &small_speed; } } if (!this->_lower_slices_bridge_speed_big.empty()) { +#ifdef _DEBUG + Points outer_points; + for(auto & line: *previous) for(auto &pt : line) outer_points.emplace_back(coord_t(pt.x()), coord_t(pt.y())); +#endif big_speed = clip_extrusion(*previous, this->_lower_slices_bridge_speed_big_clipperpaths, ClipperLib_Z::ctDifference); #ifdef _DEBUG for (ClipperLib_Z::Path& poly : big_speed) // assert big_speed @@ -2156,9 +2217,8 @@ ExtrusionPaths PerimeterGenerator::create_overhangs(const ClipperLib_Z::Path& ar if (!big_speed.empty()) { *previous = clip_extrusion(*previous, this->_lower_slices_bridge_speed_big_clipperpaths, ClipperLib_Z::ctIntersection); #ifdef _DEBUG - for (ClipperLib_Z::Path& poly : *previous) // assert previous - for (int i = 0; i < poly.size() - 1; i++) // assert previous - assert(poly[i] != poly[i + 1]); // assert previous + test_overhangs(big_speed, *previous, outer_points); + test_overhangs(*previous, big_speed, outer_points); #endif previous = &big_speed; } @@ -2166,6 +2226,10 @@ ExtrusionPaths PerimeterGenerator::create_overhangs(const ClipperLib_Z::Path& ar } if (overhangs_width > 0) { if (!this->_lower_slices_bridge_flow_small.empty()) { +#ifdef _DEBUG + Points outer_points; + for(auto & line: *previous) for(auto &pt : line) outer_points.emplace_back(coord_t(pt.x()), coord_t(pt.y())); +#endif small_flow = clip_extrusion(*previous, this->_lower_slices_bridge_flow_small_clipperpaths, ClipperLib_Z::ctDifference); #ifdef _DEBUG for (ClipperLib_Z::Path& poly : small_flow) // assert small_flow @@ -2175,14 +2239,17 @@ ExtrusionPaths PerimeterGenerator::create_overhangs(const ClipperLib_Z::Path& ar if (!small_flow.empty()) { *previous = clip_extrusion(*previous, this->_lower_slices_bridge_flow_small_clipperpaths, ClipperLib_Z::ctIntersection); #ifdef _DEBUG - for (ClipperLib_Z::Path& poly : *previous) // assert previous - for (int i = 0; i < poly.size() - 1; i++) // assert previous - assert(poly[i] != poly[i + 1]); // assert previous + test_overhangs(small_flow, *previous, outer_points); + test_overhangs(*previous, small_flow, outer_points); #endif previous = &small_flow; } } if (!this->_lower_slices_bridge_flow_big.empty()) { +#ifdef _DEBUG + Points outer_points; + for(auto & line: *previous) for(auto &pt : line) outer_points.emplace_back(coord_t(pt.x()), coord_t(pt.y())); +#endif big_flow = clip_extrusion(*previous, this->_lower_slices_bridge_flow_big_clipperpaths, ClipperLib_Z::ctDifference); #ifdef _DEBUG for (ClipperLib_Z::Path& poly : big_flow) // assert big_flow @@ -2192,9 +2259,8 @@ ExtrusionPaths PerimeterGenerator::create_overhangs(const ClipperLib_Z::Path& ar if (!big_flow.empty()) { *previous = clip_extrusion(*previous, this->_lower_slices_bridge_flow_big_clipperpaths, ClipperLib_Z::ctIntersection); #ifdef _DEBUG - for (ClipperLib_Z::Path& poly : *previous) // assert previous - for (int i = 0; i < poly.size() - 1; i++) // assert previous - assert(poly[i] != poly[i + 1]); // assert previous + test_overhangs(big_flow, *previous, outer_points); + test_overhangs(*previous, big_flow, outer_points); #endif previous = &big_flow; } @@ -2205,22 +2271,43 @@ ExtrusionPaths PerimeterGenerator::create_overhangs(const ClipperLib_Z::Path& ar if (!ok_polylines.empty()) { //fast track if (small_speed.empty() && big_speed.empty() && small_flow.empty() && big_flow.empty()) { - for (auto&& path : Geometry::unsafe_variable_width(Arachne::to_thick_polyline(arachne_path), + ExtrusionPaths thickpaths = Geometry::unsafe_variable_width(Arachne::to_thick_polyline(arachne_path), role, is_external ? this->ext_perimeter_flow : this->perimeter_flow, std::max(this->ext_perimeter_flow.scaled_width() / 4, scale_t(this->print_config->resolution)), - (is_external ? this->ext_perimeter_flow : this->perimeter_flow).scaled_width() / 10)) { + (is_external ? this->ext_perimeter_flow : this->perimeter_flow).scaled_width() / 10); +#ifdef _DEBUG + for (int i = 1; i < thickpaths.size(); i++) { + assert(thickpaths[i - 1].last_point() == thickpaths[i].first_point()); + } +#endif + assert(thickpaths.front().first_point().x() == arachne_path.front().x()); + assert(thickpaths.front().first_point().y() == arachne_path.front().y()); + assert(thickpaths.back().last_point().x() == arachne_path.back().x()); + assert(thickpaths.back().last_point().y() == arachne_path.back().y()); + for (ExtrusionPath& path : thickpaths) { path.set_can_reverse(!is_loop); paths.push_back(std::move(path)); } return paths; } for (const ClipperLib_Z::Path& extrusion_path : ok_polylines) { - for (auto&& path : Geometry::unsafe_variable_width(Arachne::to_thick_polyline(extrusion_path), + auto thick_poly = Arachne::to_thick_polyline(extrusion_path); + ExtrusionPaths thickpaths = Geometry::unsafe_variable_width(thick_poly, role, is_external ? this->ext_perimeter_flow : this->perimeter_flow, std::max(this->ext_perimeter_flow.scaled_width() / 4, scale_t(this->print_config->resolution)), - (is_external ? this->ext_perimeter_flow : this->perimeter_flow).scaled_width() / 10)) { + (is_external ? this->ext_perimeter_flow : this->perimeter_flow).scaled_width() / 10); +#ifdef _DEBUG + for (int i = 1; i < thickpaths.size(); i++) { + assert(thickpaths[i - 1].last_point() == thickpaths[i].first_point()); + } +#endif + assert(thickpaths.front().first_point().x() == extrusion_path.front().x()); + assert(thickpaths.front().first_point().y() == extrusion_path.front().y()); + assert(thickpaths.back().last_point().x() == extrusion_path.back().x()); + assert(thickpaths.back().last_point().y() == extrusion_path.back().y()); + for (ExtrusionPath& path : thickpaths) { path.set_can_reverse(!is_loop); path.height = 0; paths.push_back(std::move(path)); @@ -2229,11 +2316,21 @@ ExtrusionPaths PerimeterGenerator::create_overhangs(const ClipperLib_Z::Path& ar } if (!small_speed.empty()) { for (const ClipperLib_Z::Path& extrusion_path : small_speed) { - for (auto&& path : Geometry::unsafe_variable_width(Arachne::to_thick_polyline(extrusion_path), + ExtrusionPaths thickpaths = Geometry::unsafe_variable_width(Arachne::to_thick_polyline(extrusion_path), erOverhangPerimeter, is_external ? this->ext_perimeter_flow : this->perimeter_flow, std::max(this->ext_perimeter_flow.scaled_width() / 4, scale_t(this->print_config->resolution)), - (is_external ? this->ext_perimeter_flow : this->perimeter_flow).scaled_width() / 10)) { + (is_external ? this->ext_perimeter_flow : this->perimeter_flow).scaled_width() / 10); +#ifdef _DEBUG + for (int i = 1; i < thickpaths.size(); i++) { + assert(thickpaths[i - 1].last_point() == thickpaths[i].first_point()); + } +#endif + assert(thickpaths.front().first_point().x() == extrusion_path.front().x()); + assert(thickpaths.front().first_point().y() == extrusion_path.front().y()); + assert(thickpaths.back().last_point().x() == extrusion_path.back().x()); + assert(thickpaths.back().last_point().y() == extrusion_path.back().y()); + for (ExtrusionPath& path : thickpaths) { path.set_can_reverse(!is_loop); path.height = no_small_flow ? 2 : 1; paths.push_back(std::move(path)); @@ -2242,11 +2339,21 @@ ExtrusionPaths PerimeterGenerator::create_overhangs(const ClipperLib_Z::Path& ar } if (!big_speed.empty()) { for (const ClipperLib_Z::Path& extrusion_path : big_speed) { - for (auto&& path : Geometry::unsafe_variable_width(Arachne::to_thick_polyline(extrusion_path), + ExtrusionPaths thickpaths = Geometry::unsafe_variable_width(Arachne::to_thick_polyline(extrusion_path), erOverhangPerimeter, is_external ? this->ext_perimeter_flow : this->perimeter_flow, std::max(this->ext_perimeter_flow.scaled_width() / 4, scale_t(this->print_config->resolution)), - (is_external ? this->ext_perimeter_flow : this->perimeter_flow).scaled_width() / 10)) { + (is_external ? this->ext_perimeter_flow : this->perimeter_flow).scaled_width() / 10); +#ifdef _DEBUG + for (int i = 1; i < thickpaths.size(); i++) { + assert(thickpaths[i - 1].last_point() == thickpaths[i].first_point()); + } +#endif + assert(thickpaths.front().first_point().x() == extrusion_path.front().x()); + assert(thickpaths.front().first_point().y() == extrusion_path.front().y()); + assert(thickpaths.back().last_point().x() == extrusion_path.back().x()); + assert(thickpaths.back().last_point().y() == extrusion_path.back().y()); + for (ExtrusionPath& path : thickpaths) { path.set_can_reverse(!is_loop); path.height = no_small_flow ? 3 : 2; paths.push_back(std::move(path)); @@ -2255,11 +2362,21 @@ ExtrusionPaths PerimeterGenerator::create_overhangs(const ClipperLib_Z::Path& ar } if (!small_flow.empty()) { for (const ClipperLib_Z::Path& extrusion_path : small_flow) { - for (auto&& path : Geometry::unsafe_variable_width(Arachne::to_thick_polyline(extrusion_path), + ExtrusionPaths thickpaths = Geometry::unsafe_variable_width(Arachne::to_thick_polyline(extrusion_path), erOverhangPerimeter, is_external ? this->ext_perimeter_flow : this->perimeter_flow, std::max(this->ext_perimeter_flow.scaled_width() / 4, scale_t(this->print_config->resolution)), - (is_external ? this->ext_perimeter_flow : this->perimeter_flow).scaled_width() / 10)) { + (is_external ? this->ext_perimeter_flow : this->perimeter_flow).scaled_width() / 10); +#ifdef _DEBUG + for (int i = 1; i < thickpaths.size(); i++) { + assert(thickpaths[i - 1].last_point() == thickpaths[i].first_point()); + } +#endif + assert(thickpaths.front().first_point().x() == extrusion_path.front().x()); + assert(thickpaths.front().first_point().y() == extrusion_path.front().y()); + assert(thickpaths.back().last_point().x() == extrusion_path.back().x()); + assert(thickpaths.back().last_point().y() == extrusion_path.back().y()); + for (ExtrusionPath& path : thickpaths) { // change flow to overhang one if too much. if (path.mm3_per_mm > this->overhang_flow.mm3_per_mm() ){ path.mm3_per_mm = this->overhang_flow.mm3_per_mm(); @@ -2274,11 +2391,21 @@ ExtrusionPaths PerimeterGenerator::create_overhangs(const ClipperLib_Z::Path& ar } if (!big_flow.empty()) { for (const ClipperLib_Z::Path& extrusion_path : big_flow) { - for (auto&& path : Geometry::unsafe_variable_width(Arachne::to_thick_polyline(extrusion_path), + ExtrusionPaths thickpaths = Geometry::unsafe_variable_width(Arachne::to_thick_polyline(extrusion_path), erOverhangPerimeter, is_external ? this->ext_perimeter_flow : this->perimeter_flow, std::max(this->ext_perimeter_flow.scaled_width() / 4, scale_t(this->print_config->resolution)), - (is_external ? this->ext_perimeter_flow : this->perimeter_flow).scaled_width() / 10)) { + (is_external ? this->ext_perimeter_flow : this->perimeter_flow).scaled_width() / 10); +#ifdef _DEBUG + for (int i = 1; i < thickpaths.size(); i++) { + assert(thickpaths[i - 1].last_point() == thickpaths[i].first_point()); + } +#endif + assert(thickpaths.front().first_point().x() == extrusion_path.front().x()); + assert(thickpaths.front().first_point().y() == extrusion_path.front().y()); + assert(thickpaths.back().last_point().x() == extrusion_path.back().x()); + assert(thickpaths.back().last_point().y() == extrusion_path.back().y()); + for (ExtrusionPath& path : thickpaths) { // change flow to overhang one if too much. if (path.mm3_per_mm > this->overhang_flow.mm3_per_mm()) { path.mm3_per_mm = this->overhang_flow.mm3_per_mm(); @@ -2299,6 +2426,21 @@ ExtrusionPaths PerimeterGenerator::create_overhangs(const ClipperLib_Z::Path& ar if (!paths.empty()) chain_and_reorder_extrusion_paths(paths, &paths.front().first_point()); + for (int i = 1; i < paths.size(); i++) { + // diff/inter can generate points with ~3-5 unit of diff. + if (paths[i - 1].last_point() != paths[i].first_point()) { + assert(paths[i - 1].last_point().coincides_with_epsilon(paths[i].first_point())); + Point middle = (paths[i - 1].last_point() + paths[i].first_point()) / 2; + paths[i - 1].polyline.set_points().back() = middle; + paths[i].polyline.set_points().front() = middle; + } + } +#ifdef _DEBUG + for (int i = 1; i < paths.size(); i++) { + assert(paths[i - 1].last_point() == paths[i].first_point()); + } +#endif + bool has_normal = !ok_polylines.empty(); bool has_speed = !small_speed.empty() || !big_speed.empty(); bool has_flow = !small_flow.empty() || !big_flow.empty(); @@ -2342,11 +2484,6 @@ ExtrusionPaths PerimeterGenerator::create_overhangs(const ClipperLib_Z::Path& ar if (paths.size() > 2) { double min_length = this->perimeter_flow.scaled_width() * 2; double ok_length = this->perimeter_flow.scaled_width() * 20; -#ifdef _DEBUG - for (int i = 1; i < paths.size(); i++) { - assert(paths[i - 1].last_point() == paths[i].first_point()); - } -#endif foreach(paths, [min_length, ok_length](ExtrusionPath& prev, ExtrusionPath& curr, ExtrusionPath& next) { assert(prev.last_point() == curr.first_point()); if (curr.length() < min_length) { From 5ee5531538a2bf5691fc8f4421662822a4c3e3aa Mon Sep 17 00:00:00 2001 From: supermerill Date: Mon, 15 Jan 2024 19:19:08 +0100 Subject: [PATCH 14/25] fix de7041 : filament compatible widget supermerill/SuperSlicer#4073 --- src/slic3r/GUI/Tab.cpp | 30 +++++++++++++++--------------- src/slic3r/GUI/Tab.hpp | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index a6c7b580ed8..a234e67b69a 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2004,18 +2004,6 @@ std::vector Tab::create_pages(std::string setting_type_nam continue; } - if (setting_id == "compatible_printers") { - create_line_with_widget(current_group.get(), "compatible_printers", "", [this](wxWindow* parent) { - return compatible_widget_create(parent, m_compatible_printers); - }); - continue; - } else if (setting_id == "compatible_prints") { - create_line_with_widget(current_group.get(), "compatible_prints", "", [this](wxWindow* parent) { - return compatible_widget_create(parent, m_compatible_prints); - }); - continue; - } - int id = -1; for (int i = 1; i < params.size() - 1; i++) { if (boost::starts_with(params[i], "id$")) @@ -2024,6 +2012,18 @@ std::vector Tab::create_pages(std::string setting_type_nam id = idx_page; } + if (setting_id == "compatible_printers") { + create_line_with_widget(current_group.get(), "compatible_printers", "", [this, id](wxWindow* parent) { + return compatible_widget_create(parent, m_compatible_printers, id); + }); + continue; + } else if (setting_id == "compatible_prints") { + create_line_with_widget(current_group.get(), "compatible_prints", "", [this, id](wxWindow* parent) { + return compatible_widget_create(parent, m_compatible_prints, id); + }); + continue; + } + Option option = is_script ? Option(ConfigOptionDef{}, setting_id) : current_group->create_option_from_def(setting_id, id); @@ -4485,7 +4485,7 @@ void Tab::create_line_with_widget(ConfigOptionsGroup* optgroup, const std::strin } // Return a callback to create a Tab widget to mark the preferences as compatible / incompatible to the current printer. -wxSizer* Tab::compatible_widget_create(wxWindow* parent, PresetDependencies &deps) +wxSizer* Tab::compatible_widget_create(wxWindow* parent, PresetDependencies &deps, int setting_idx) { deps.checkbox = new wxCheckBox(parent, wxID_ANY, _(L("All"))); deps.checkbox->SetFont(Slic3r::GUI::wxGetApp().normal_font()); @@ -4499,13 +4499,13 @@ wxSizer* Tab::compatible_widget_create(wxWindow* parent, PresetDependencies &dep sizer->Add((deps.checkbox), 0, wxALIGN_CENTER_VERTICAL); sizer->Add((deps.btn), 0, wxALIGN_CENTER_VERTICAL); - deps.checkbox->Bind(wxEVT_CHECKBOX, ([this, &deps](wxCommandEvent e) + deps.checkbox->Bind(wxEVT_CHECKBOX, ([this, &deps, setting_idx](wxCommandEvent e) { deps.btn->Enable(! deps.checkbox->GetValue()); // All printers have been made compatible with this preset. if (deps.checkbox->GetValue()) this->load_key_value(deps.key_list, std::vector {}); - this->get_field(deps.key_condition)->toggle(deps.checkbox->GetValue()); + this->get_field(deps.key_condition, setting_idx)->toggle(deps.checkbox->GetValue()); this->update_changed_ui(); }) ); diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index c3bf7b6dc16..f601c01d59d 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -482,7 +482,7 @@ class Tab: public wxPanel static t_change set_or_add(t_change previous, t_change toadd); protected: void create_line_with_widget(ConfigOptionsGroup* optgroup, const std::string& opt_key, const std::string& path, widget_t widget); - wxSizer* compatible_widget_create(wxWindow* parent, PresetDependencies &deps); + wxSizer* compatible_widget_create(wxWindow* parent, PresetDependencies &deps, int setting_idx); void compatible_widget_reload(PresetDependencies &deps); void load_key_value(const std::string& opt_key, const boost::any& value, bool saved_value = false); From e08942f09bff7b7582cdae6d1ef20c22d38e2428 Mon Sep 17 00:00:00 2001 From: supermerill Date: Tue, 16 Jan 2024 10:18:06 +0100 Subject: [PATCH 15/25] reworked parallel_objects_step to be able to print objects instances in sequence. supermerill/SuperSlicer#4043 --- src/libslic3r/GCode.cpp | 122 ++++++++++++++++++++-------------------- src/libslic3r/GCode.hpp | 2 +- 2 files changed, 61 insertions(+), 63 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index ce20991b3a2..c87f6233760 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -1538,7 +1538,7 @@ void GCode::_do_export(Print& print_mod, GCodeOutputStream &file, ThumbnailsGene } } } - if (print.config().complete_objects.value) { + if (print.config().complete_objects.value || print.config().parallel_objects_step.value > 0) { // Order object instances for sequential print. if(print.config().complete_objects_sort.value == cosObject) print_object_instances_ordering = sort_object_instances_by_model_order(print); @@ -1848,24 +1848,7 @@ void GCode::_do_export(Print& print_mod, GCodeOutputStream &file, ThumbnailsGene print.throw_if_canceled(); this->set_origin(unscale((*print_object_instance_sequential_active)->shift)); if (finished_objects > 0) { - // Move to the origin position for the copy we're going to print. - // This happens before Z goes down to layer 0 again, so that no collision happens hopefully. - m_enable_cooling_markers = false; // we're not filtering these moves through CoolingBuffer - m_avoid_crossing_perimeters.use_external_mp_once(); - set_extra_lift(m_last_layer_z, 0, print.config(), m_writer, initial_extruder_id); - file.write(this->retract()); - std::string gcode; - //go to origin of the next object (it's 0,0 because we shifted the origin to it) - Polyline polyline = this->travel_to(gcode, Point(0, 0), erTravel); - this->write_travel_to(gcode, polyline, "move to origin position for next object"); - file.write(gcode); - m_enable_cooling_markers = true; - // Disable motion planner when traveling to first object point. - m_avoid_crossing_perimeters.disable_once(); - // Ff we are printing the bottom layer of an object, and we have already finished - // another one, set first layer temperatures. This happens before the Z move - // is triggered, so machine has more time to reach such temperatures. - m_placeholder_parser.set("current_object_idx", int(finished_objects)); + _move_to_print_object(file, print, finished_objects, initial_extruder_id); std::string between_objects_gcode = this->placeholder_parser_process("between_objects_gcode", print.config().between_objects_gcode.value, initial_extruder_id); // Set first layer bed and extruder temperatures, don't wait for it to reach the temperature. this->_print_first_layer_bed_temperature(file, print, between_objects_gcode, initial_extruder_id, false); @@ -1894,57 +1877,50 @@ void GCode::_do_export(Print& print_mod, GCodeOutputStream &file, ThumbnailsGene } else { /////////////////////////////////////////////// begin parallel_objects_step if (print.config().parallel_objects_step > 0 && !has_wipe_tower) { - - float range = print.config().parallel_objects_step + EPSILON; - print_object_instances_ordering = sort_object_instances_by_model_order(print); - std::vector::const_iterator prev_object = print_object_instances_ordering.begin(); - - bool first_layer = true; - proceed_layers: + double range = std::min(print.config().parallel_objects_step, print.config().extruder_clearance_height) + EPSILON; + print_object_instances_ordering = chain_print_object_instances(print); + bool first_layers = true; for (coordf_t Rstart = 0, Rend = range;; Rstart += range, Rend += range) { + proceed_layers: bool is_layers = false; - print_object_instance_sequential_active = print_object_instances_ordering.begin(); - - for (size_t i = 0; i < print.objects().size(); ++i, ++print_object_instance_sequential_active) { - std::vector>> layers_to_print_range; - { - std::vector object_layers = collect_layers_to_print(*print.objects()[i], status_monitor); - int layer_num = 0; - for (LayerToPrint& ltp : object_layers) { - layer_num++; - if (!first_layer && layer_num == 1) - continue; - - if (ltp.print_z() >= Rstart && ltp.print_z() < Rend) { - std::pair> merged; - merged.first = ltp.print_z(); - merged.second.push_back(std::move(ltp)); - layers_to_print_range.emplace_back(merged); - if (first_layer) - break; - } - } + for (auto it_print_object_instance = print_object_instances_ordering.begin(); + it_print_object_instance != print_object_instances_ordering.end(); + ++it_print_object_instance) { + std::vector layers_to_print_range; + const PrintObject & object = *(*it_print_object_instance)->print_object; + std::vector object_layers = collect_layers_to_print(object, status_monitor); + + for (const LayerToPrint <p : object_layers) { + if (ltp.print_z() < Rstart || ltp.print_z() >= Rend) + continue; + + if (!first_layers && ltp.layer()->id() == 0) + continue; + + layers_to_print_range.push_back(ltp); + if (first_layers) + break; } - if (!layers_to_print_range.empty()) - { - if (print_object_instance_sequential_active != prev_object) { - this->set_origin(unscale((*print_object_instance_sequential_active)->shift)); - std::string gcode; - //go to origin of the next object (it's 0,0 because we shifted the origin to it) - Polyline polyline = this->travel_to(gcode, Point(0, 0), erTravel); - this->write_travel_to(gcode, polyline, "move to origin position for next object"); - file.write(gcode); - } - this->process_layers(print, status_monitor, tool_ordering, print_object_instances_ordering, - layers_to_print_range, file); - prev_object = print_object_instance_sequential_active; + if (!layers_to_print_range.empty()) { + this->set_origin(unscale((*it_print_object_instance)->shift)); + + size_t finished_objects = 1 + (it_print_object_instance - + print_object_instances_ordering.begin()); + if (finished_objects > 1) + _move_to_print_object(file, print, finished_objects, initial_extruder_id); + + assert(!object.instances().empty()); + assert(*it_print_object_instance >= &*object.instances().begin() && + *it_print_object_instance <= &*(object.instances().end()-1)); + this->process_layers(print, status_monitor, tool_ordering, layers_to_print_range, + *it_print_object_instance - object.instances().data(), file); is_layers = true; } } - if (first_layer) { - first_layer = false; + if (first_layers) { + first_layers = false; goto proceed_layers; } if (!is_layers) { @@ -2107,6 +2083,28 @@ void GCode::_do_export(Print& print_mod, GCodeOutputStream &file, ThumbnailsGene print.throw_if_canceled(); } +void GCode::_move_to_print_object(GCodeOutputStream& file, const Print& print, size_t finished_objects, uint16_t initial_extruder_id) +{ + // Move to the origin position for the copy we're going to print. + // This happens before Z goes down to layer 0 again, so that no collision happens hopefully. + m_enable_cooling_markers = false; // we're not filtering these moves through CoolingBuffer + m_avoid_crossing_perimeters.use_external_mp_once(); + set_extra_lift(m_last_layer_z, 0, print.config(), m_writer, initial_extruder_id); + file.write(this->retract()); + std::string gcode; + //go to origin of the next object (it's 0,0 because we shifted the origin to it) + Polyline polyline = this->travel_to(gcode, Point(0, 0), erTravel); + this->write_travel_to(gcode, polyline, "move to origin position for next object"); + file.write(gcode); + m_enable_cooling_markers = true; + // Disable motion planner when traveling to first object point. + m_avoid_crossing_perimeters.disable_once(); + // Ff we are printing the bottom layer of an object, and we have already finished + // another one, set first layer temperatures. This happens before the Z move + // is triggered, so machine has more time to reach such temperatures. + m_placeholder_parser.set("current_object_idx", int(finished_objects)); +} + // For unknown reasons and in sporadic cases when GCode export is processing, some participating thread // in tbb::parallel_pipeline has not set locales to "C", probably because this thread is newly spawned. // So in this class method on_scheduler_entry is called for every thread before it starts participating diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index 5a42e0bfe87..ee39812c0a9 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -245,7 +245,7 @@ class GCode : ExtrusionVisitorConst { GCode &m_gcodegen; }; void _do_export(Print &print, GCodeOutputStream &file, ThumbnailsGeneratorCallback thumbnail_cb); - + void _move_to_print_object(GCodeOutputStream& file, const Print& print, size_t finished_objects, uint16_t initial_extruder_id); void _init_multiextruders(const Print& print, GCodeOutputStream& file, GCodeWriter& writer, const ToolOrdering& tool_ordering, const std::string& custom_gcode); static std::vector collect_layers_to_print(const PrintObject &object, Print::StatusMonitor &status_monitor); From 1f7d68b3f5c65a5c25a9bcbff2927373d60ad57b Mon Sep 17 00:00:00 2001 From: supermerill Date: Tue, 16 Jan 2024 10:32:34 +0100 Subject: [PATCH 16/25] fix only_one_perimeter_top for arachne supermerill/SuperSlicer#4041 --- src/libslic3r/PerimeterGenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index d3f01c621f4..c8a903166b0 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -253,7 +253,7 @@ ProcessSurfaceResult PerimeterGenerator::process_arachne(int& loop_number, const // svg.draw(to_polylines(last), "brown"); // svg.Close(); //} - loop_number = 0; + loop_number--; } else { // Give up the outer shell because we don't have any meaningful top surface out_shell.clear(); From 1f96533531f2285cdf9f4bf5ae817bbf25787dd1 Mon Sep 17 00:00:00 2001 From: supermerill Date: Tue, 16 Jan 2024 11:45:16 +0100 Subject: [PATCH 17/25] Fix infill speeds in modifier don't work if not altering the full layer supermerill/SuperSlicer#3849 --- src/libslic3r/Fill/Fill.cpp | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index fd6774661a5..25ff8a77273 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -60,17 +60,45 @@ struct SurfaceFillParams : FillParams RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, connection); RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, dont_adjust); - RETURN_COMPARE_NON_EQUAL(anchor_length); RETURN_COMPARE_NON_EQUAL(fill_exactly); + RETURN_COMPARE_NON_EQUAL(anchor_length); + RETURN_COMPARE_NON_EQUAL(fill_exactly); RETURN_COMPARE_NON_EQUAL(flow.width()); RETURN_COMPARE_NON_EQUAL(flow.height()); RETURN_COMPARE_NON_EQUAL(flow.nozzle_diameter()); RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, flow.bridge()); RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, role); RETURN_COMPARE_NON_EQUAL_TYPED(int32_t, priority); + assert(this->config != nullptr); + assert(rhs.config != nullptr); + if (config != nullptr && rhs.config != nullptr) { + RETURN_COMPARE_NON_EQUAL(config->infill_speed); + RETURN_COMPARE_NON_EQUAL(config->solid_infill_speed); + RETURN_COMPARE_NON_EQUAL(config->top_solid_infill_speed); + RETURN_COMPARE_NON_EQUAL(config->ironing_speed); + RETURN_COMPARE_NON_EQUAL(config->default_speed); + RETURN_COMPARE_NON_EQUAL(config->bridge_speed); + RETURN_COMPARE_NON_EQUAL(config->bridge_speed_internal); + RETURN_COMPARE_NON_EQUAL(config->gap_fill_speed); + } + assert(*this == rhs); return false; } bool operator==(const SurfaceFillParams &rhs) const { + // first check speed via config + if ((config != nullptr) != (rhs.config != nullptr)) + return false; + if(config != nullptr && ( + config->infill_speed != rhs.config->infill_speed + || config->solid_infill_speed != rhs.config->solid_infill_speed + || config->top_solid_infill_speed != rhs.config->top_solid_infill_speed + || config->ironing_speed != rhs.config->ironing_speed + || config->default_speed != rhs.config->default_speed + || config->bridge_speed != rhs.config->bridge_speed + || config->bridge_speed_internal != rhs.config->bridge_speed_internal + || config->gap_fill_speed != rhs.config->gap_fill_speed)) + return false; + // then check params return this->extruder == rhs.extruder && this->pattern == rhs.pattern && this->spacing == rhs.spacing && From c70bb56683e151f1dbbd04111af617f5e591b6d9 Mon Sep 17 00:00:00 2001 From: Icenowy Zheng Date: Tue, 16 Jan 2024 19:33:20 +0800 Subject: [PATCH 18/25] fix NULL dereference on wxWidgets 3.2 According to the document of wxWidgets, the initializer of wxLocale with no parameters do not do any initialization at all, thus do not register its wxTranslations. Explicitly call Init() with its default parameters to init it with the default setting, otherwise on Linux with wxWidgets 3.2, the wxTranslations singleton get is NULL and lead to NULL deference. The code here is from PrusaSlicer 2.5 [1]. [1] https://github.com/prusa3d/PrusaSlicer/commit/e21921f2ebd2b94c57459bd280f1b1bd8eec1b9c Signed-off-by: Icenowy Zheng --- src/slic3r/GUI/GUI_App.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index a43a77ee1e0..b6b806c6afc 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -2289,6 +2289,15 @@ bool GUI_App::load_language(wxString language, bool initial) { // Allocating a temporary locale will switch the default wxTranslations to its internal wxTranslations instance. wxLocale temp_locale; +#ifdef __WXOSX__ + // ysFIXME - temporary workaround till it isn't fixed in wxWidgets: + // Use English as an initial language, because of under OSX it try to load "inappropriate" language for wxLANGUAGE_DEFAULT. + // For example in our case it's trying to load "en_CZ" and as a result PrusaSlicer catch warning message. + // But wxWidgets guys work on it. + temp_locale.Init(wxLANGUAGE_ENGLISH); +#else + temp_locale.Init(); +#endif // __WXOSX__ // Set the current translation's language to default, otherwise GetBestTranslation() may not work (see the wxWidgets source code). wxTranslations::Get()->SetLanguage(wxLANGUAGE_DEFAULT); // Let the wxFileTranslationsLoader enumerate all translation dictionaries for PrusaSlicer From 5a124ef445861a35c5ec16635f723649b631f413 Mon Sep 17 00:00:00 2001 From: supermerill Date: Tue, 16 Jan 2024 11:56:56 +0100 Subject: [PATCH 19/25] Change text from "odd" to "even" as the layer numbering began by 1 and not 0 in the gui. also some other cosmetic changes --- resources/ui_layout/default/filament.ui | 2 +- resources/ui_layout/default/print.ui | 12 ++++---- resources/ui_layout/example/print.ui | 8 +++--- src/libslic3r/PrintConfig.cpp | 37 +++++++++++++------------ src/slic3r/GUI/ConfigManipulation.cpp | 8 ++++-- 5 files changed, 35 insertions(+), 32 deletions(-) diff --git a/resources/ui_layout/default/filament.ui b/resources/ui_layout/default/filament.ui index 5b9ad60732d..7aa065d2ba5 100644 --- a/resources/ui_layout/default/filament.ui +++ b/resources/ui_layout/default/filament.ui @@ -50,7 +50,7 @@ group:Fan speed - default setting:id$0:label_width$12:label$Gap fill:gap_fill_fan_speed line:Disable fan for the first setting:id$0:width$5:label$_:sidetext_width$7:disable_fan_first_layers - setting:id$0:width$5:label_width$12:full_fan_speed_layer + setting:id$0:width$5:label_width$18:full_fan_speed_layer end_line group:Short layer time - began to increase base fan speed setting:id$0:fan_below_layer_time diff --git a/resources/ui_layout/default/print.ui b/resources/ui_layout/default/print.ui index b07794e5d28..959d028473a 100644 --- a/resources/ui_layout/default/print.ui +++ b/resources/ui_layout/default/print.ui @@ -389,10 +389,10 @@ group:label_width$9:sidetext_width$8:Acceleration control (advanced) setting:width$4:ironing_acceleration line:Travel acceleration setting:width$4:travel_acceleration - setting:width$4:travel_deceleration_use_target + setting:label_width$22:travel_deceleration_use_target line:First layer acceleration setting:width$4:first_layer_acceleration - setting:label_width$35:width$4:first_layer_acceleration_over_raft + setting:label_width$22:width$4:first_layer_acceleration_over_raft end_line page:Width & Flow:width @@ -408,22 +408,22 @@ group:Extrusion width line:perimeter setting:sidetext_width$10:label$width:perimeter_extrusion_width setting:sidetext_width$10:label_width$15:label$spacing:perimeter_extrusion_spacing - setting:sidetext_width$10:label_width$15:label$odd layers:perimeter_extrusion_change_odd_layers + setting:sidetext_width$10:label_width$15:label$even layers:perimeter_extrusion_change_odd_layers end_line line:external perimeter setting:sidetext_width$10:label$width:external_perimeter_extrusion_width setting:sidetext_width$10:label_width$15:label$width&spacing combo:external_perimeter_extrusion_spacing - setting:sidetext_width$10:label_width$15:label$odd layers:external_perimeter_extrusion_change_odd_layers + setting:sidetext_width$10:label_width$15:label$even layers:external_perimeter_extrusion_change_odd_layers end_line line:infill setting:sidetext_width$10:label$width:infill_extrusion_width setting:sidetext_width$10:label_width$15:label$spacing:infill_extrusion_spacing - setting:sidetext_width$10:label_width$15:label$odd layers:infill_extrusion_change_odd_layers + setting:sidetext_width$10:label_width$15:label$even layers:infill_extrusion_change_odd_layers end_line line:solid infill setting:sidetext_width$10:label$width:solid_infill_extrusion_width setting:sidetext_width$10:label_width$15:label$spacing:solid_infill_extrusion_spacing - setting:sidetext_width$10:label_width$15:label$odd layers:solid_infill_extrusion_change_odd_layers + setting:sidetext_width$10:label_width$15:label$even layers:solid_infill_extrusion_change_odd_layers end_line line:top infill setting:sidetext_width$10:label$width:top_infill_extrusion_width diff --git a/resources/ui_layout/example/print.ui b/resources/ui_layout/example/print.ui index 86badd553a9..5d90c54bdaf 100644 --- a/resources/ui_layout/example/print.ui +++ b/resources/ui_layout/example/print.ui @@ -393,22 +393,22 @@ group:Extrusion width line:perimeter setting:sidetext_width$10:label$width:perimeter_extrusion_width setting:sidetext_width$10:label_width$15:label$spacing:perimeter_extrusion_spacing - setting:sidetext_width$10:label_width$15:label$odd layers:perimeter_extrusion_change_odd_layers + setting:sidetext_width$10:label_width$15:label$even layers:perimeter_extrusion_change_odd_layers end_line line:external perimeter setting:sidetext_width$10:label$width:external_perimeter_extrusion_width setting:sidetext_width$10:label_width$15:label$width&spacing combo:external_perimeter_extrusion_spacing - setting:sidetext_width$10:label_width$15:label$odd layers:external_perimeter_extrusion_change_odd_layers + setting:sidetext_width$10:label_width$15:label$even layers:external_perimeter_extrusion_change_odd_layers end_line line:infill setting:sidetext_width$10:label$width:infill_extrusion_width setting:sidetext_width$10:label_width$15:label$spacing:infill_extrusion_spacing - setting:sidetext_width$10:label_width$15:label$odd layers:infill_extrusion_change_odd_layers + setting:sidetext_width$10:label_width$15:label$even layers:infill_extrusion_change_odd_layers end_line line:solid infill setting:sidetext_width$10:label$width:solid_infill_extrusion_width setting:sidetext_width$10:label_width$15:label$spacing:solid_infill_extrusion_spacing - setting:sidetext_width$10:label_width$15:label$odd layers:solid_infill_extrusion_change_odd_layers + setting:sidetext_width$10:label_width$15:label$even layers:solid_infill_extrusion_change_odd_layers end_line line:top infill setting:sidetext_width$10:label$width:top_infill_extrusion_width diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 609366e7c21..e34aa7dc806 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -425,7 +425,7 @@ void PrintConfigDef::init_common_params() def = this->add("thumbnails_tag_format", coBool); def->label = L("Write the thumbnail type in gcode."); def->tooltip = L("instead of writing 'thumbnails' as tag in the gcode, it will write 'thumbnails_PNG', thumbnails_JPG', 'thumbnail_QOI', etc.." - "\n Some firmware needs it to know how to decode the thumbnail, some others don't support it."); + "\n Some firmware need it to know how to decode the thumbnail, some others don't support it."); def->mode = comExpert | comSuSi; def->set_default_value(new ConfigOptionBool(false)); @@ -1524,11 +1524,11 @@ void PrintConfigDef::init_fff_params() def = this->add("external_perimeter_extrusion_change_odd_layers", coFloatOrPercent); def->label = L("External perimeters"); - def->full_label = L("External perimeters spacing change on odd layers"); + def->full_label = L("External perimeters spacing change on even layers"); def->category = OptionCategory::width; - def->tooltip = L("Change width on every odd layer for better overlap with adjacent layers and getting stringer shells. " + def->tooltip = L("Change width on every even layer (and not on odd layers like the first one) for better overlap with adjacent layers and getting stringer shells. " "Try values about +/- 0.1 with different sign for external and internal perimeters." - "\nThis could be combined with extra permeters on odd layers." + "\nThis could be combined with extra permeters on even layers." "\nWorks as absolute spacing or a % of the spacing." "\nset 0 to disable"); def->sidetext = L("mm or %"); @@ -1661,10 +1661,10 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionBool(false)); def = this->add("extra_perimeters_odd_layers", coBool); - def->label = L("On odd layers"); - def->full_label = L("Extra perimeter on odd layers"); + def->label = L("On even layers"); + def->full_label = L("Extra perimeter on even layers"); def->category = OptionCategory::perimeter; - def->tooltip = L("Add one perimeter every odd layer. With this, infill is taken into the sandwich" + def->tooltip = L("Add one perimeter every even layer (and not on odd layers like the first one). With this, infill is taken into the sandwich" " and you may be able to reduce drastically the infill/perimeter overlap setting. "); def->mode = comAdvancedE | comSuSi; def->set_default_value(new ConfigOptionBool(false)); @@ -3149,11 +3149,11 @@ void PrintConfigDef::init_fff_params() def = this->add("infill_extrusion_change_odd_layers", coFloatOrPercent); def->label = L("Infill"); - def->full_label = L("Infill spacing change on odd layers"); + def->full_label = L("Infill spacing change on even layers"); def->category = OptionCategory::width; - def->tooltip = L("Change width on every odd layer for better overlap with adjacent layers and getting stringer shells. " + def->tooltip = L("Change width on every even layer (and not on odd layers like the first one) for better overlap with adjacent layers and getting stringer shells. " "Try values about +/- 0.1 with different sign." - "\nThis could be combined with extra permeters on odd layers." + "\nThis could be combined with extra permeters on even layers." "\nWorks as absolute spacing or a % of the spacing." "\nset 0 to disable"); def->sidetext = L("mm or %"); @@ -4001,10 +4001,11 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionFloatOrPercent(75, true)); def = this->add("overhangs_reverse", coBool); - def->label = L("Reverse on odd"); + def->label = L("Reverse on even"); def->full_label = L("Overhang reversal"); def->category = OptionCategory::perimeter; - def->tooltip = L("Extrude perimeters that have a part over an overhang in the reverse direction on odd layers. This alternating pattern can drastically improve steep overhang." + def->tooltip = L("Extrude perimeters that have a part over an overhang in the reverse direction on even layers (and not on odd layers like the first one)." + " This alternating pattern can drastically improve steep overhang." "\n!! this is a very slow algorithm (it uses the same results as extra_perimeters_overhangs) !!"); def->mode = comAdvancedE | comSuSi; def->set_default_value(new ConfigOptionBool(false)); @@ -4142,11 +4143,11 @@ void PrintConfigDef::init_fff_params() def = this->add("perimeter_extrusion_change_odd_layers", coFloatOrPercent); def->label = L("Perimeters"); - def->full_label = L("Perimeters spacing change on odd layers"); + def->full_label = L("Perimeters spacing change on even layers"); def->category = OptionCategory::width; - def->tooltip = L("Change width on every odd layer for better overlap with adjacent layers and getting stringer shells. " + def->tooltip = L("Change width on every even layer (and not on odd layers like the first one) for better overlap with adjacent layers and getting stringer shells. " "Try values about +/- 0.1 with different sign for external and internal perimeters." - "\nThis could be combined with extra permeters on odd layers." + "\nThis could be combined with extra permeters on even layers." "\nWorks as absolute spacing or a % of the spacing." "\nset 0 to disable"); def->sidetext = L("mm or %"); @@ -4968,11 +4969,11 @@ void PrintConfigDef::init_fff_params() def = this->add("solid_infill_extrusion_change_odd_layers", coFloatOrPercent); def->label = L("Infill"); - def->full_label = L("Solid infill spacing change on odd layers"); + def->full_label = L("Solid infill spacing change on even layers"); def->category = OptionCategory::width; - def->tooltip = L("Change width on every odd layer for better overlap with adjacent layers and getting stringer shells. " + def->tooltip = L("Change width on every even layer (and not on odd layers like the first one) for better overlap with adjacent layers and getting stringer shells. " "Try values about +/- 0.1 with different sign." - "\nThis could be combined with extra permeters on odd layers." + "\nThis could be combined with extra permeters on even layers." "\nWorks as absolute spacing or a % of the spacing." "\nset 0 to disable"); def->sidetext = L("mm or %"); diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 5f585fe7ece..f787582510f 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -389,9 +389,6 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config) for (auto el : { "fuzzy_skin_thickness", "fuzzy_skin_point_dist" }) toggle_field(el, config->option>("fuzzy_skin")->value != FuzzySkinType::None); - toggle_field("avoid_crossing_not_first_layer", config->opt_bool("avoid_crossing_perimeters")); - toggle_field("avoid_crossing_top", config->opt_bool("avoid_crossing_perimeters")); - bool have_infill = config->option("fill_density")->value > 0; // infill_extruder uses the same logic as in Print::extruders() for (auto el : { "fill_pattern", "infill_connection", "infill_every_layers", "infill_only_where_needed", @@ -549,6 +546,11 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config) bool have_avoid_crossing_perimeters = config->opt_bool("avoid_crossing_perimeters"); toggle_field("avoid_crossing_perimeters_max_detour", have_avoid_crossing_perimeters); + toggle_field("avoid_crossing_not_first_layer", have_avoid_crossing_perimeters); + toggle_field("avoid_crossing_top", have_avoid_crossing_perimeters); + + toggle_field("enforce_retract_first_layer", config->opt_bool("only_retract_when_crossing_perimeters")); + for (auto el : { "fill_smooth_width", "fill_smooth_distribution" }) toggle_field(el, (has_top_solid_infill && config->option>("top_fill_pattern")->value == InfillPattern::ipSmooth) From 917a5d7d85d875da3d137810bd00d67577c8bbd9 Mon Sep 17 00:00:00 2001 From: supermerill Date: Wed, 17 Jan 2024 12:18:05 +0100 Subject: [PATCH 20/25] More tests (& fixes) for fills with enforce_full_fill_volume --- src/libslic3r/ExtrusionEntity.cpp | 8 ++ src/libslic3r/ExtrusionEntity.hpp | 23 ++++- src/libslic3r/Fill/Fill.cpp | 22 +++++ src/libslic3r/Fill/FillConcentric.cpp | 36 ++++++- src/libslic3r/Fill/FillRectilinear.cpp | 59 ++++++------ src/libslic3r/Fill/FillSmooth.cpp | 2 +- src/libslic3r/PerimeterGenerator.cpp | 2 +- tests/superslicerlibslic3r/test_fill.cpp | 115 +++++++++++++++-------- 8 files changed, 193 insertions(+), 74 deletions(-) diff --git a/src/libslic3r/ExtrusionEntity.cpp b/src/libslic3r/ExtrusionEntity.cpp index 2d610338c42..0d83edd8c98 100644 --- a/src/libslic3r/ExtrusionEntity.cpp +++ b/src/libslic3r/ExtrusionEntity.cpp @@ -494,6 +494,14 @@ void ExtrusionLength::use(const ExtrusionEntityCollection& collection) { } } +double ExtrusionVolume::get(const ExtrusionEntityCollection &coll) { + for (const ExtrusionEntity *entity : coll.entities()) entity->visit(*this); + return volume; +} + +void ExtrusionModifyFlow::set(ExtrusionEntityCollection &coll) { + for (ExtrusionEntity *entity : coll.entities()) entity->visit(*this); +} void ExtrusionVisitorRecursiveConst::use(const ExtrusionMultiPath& multipath) { for (const ExtrusionPath& path : multipath.paths) { diff --git a/src/libslic3r/ExtrusionEntity.hpp b/src/libslic3r/ExtrusionEntity.hpp index 6bc37026572..719f69cce0c 100644 --- a/src/libslic3r/ExtrusionEntity.hpp +++ b/src/libslic3r/ExtrusionEntity.hpp @@ -646,7 +646,7 @@ class ExtrusionPrinter : public ExtrusionVisitorConst { }; class ExtrusionLength : public ExtrusionVisitorConst { - double dist; + coordf_t dist; public: ExtrusionLength() : dist(0){ } virtual void default_use(const ExtrusionEntity& path) override; @@ -701,6 +701,27 @@ class GetPathsVisitor : public ExtrusionVisitorRecursive { } }; +class ExtrusionVolume : public ExtrusionVisitorRecursiveConst { + bool _with_gap_fill = true; +public: + double volume = 0; //unscaled + ExtrusionVolume(bool with_gap_fill = true) : _with_gap_fill(with_gap_fill) {} + void use(const ExtrusionPath &path) override { + if(path.role() == erGapFill && !_with_gap_fill) return; + volume += unscaled(path.length()) * path.mm3_per_mm; } + void use(const ExtrusionPath3D &path3D) override { volume += unscaled(path3D.length()) * path3D.mm3_per_mm; } + double get(const ExtrusionEntityCollection &coll); +}; + +class ExtrusionModifyFlow : public ExtrusionVisitorRecursive { + double _flow_mult = 1.; +public: + ExtrusionModifyFlow(double flow_mult) : _flow_mult(flow_mult) {} + void use(ExtrusionPath &path) override { path.mm3_per_mm *= _flow_mult; path.width *= _flow_mult; } + void use(ExtrusionPath3D &path3D) override { path3D.mm3_per_mm *= _flow_mult; path3D.width *= _flow_mult; } + void set(ExtrusionEntityCollection &coll); +}; + #if _DEBUG struct LoopAssertVisitor : public ExtrusionVisitorRecursiveConst { diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index 25ff8a77273..ea695fefac3 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -677,7 +677,29 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive: //make fill while ((size_t)surface_fill.params.priority >= fills_by_priority.size()) fills_by_priority.push_back(new ExtrusionEntityCollection()); +#if _DEBUG + const size_t idx_start = fills_by_priority[(size_t)surface_fill.params.priority]->entities().size(); +#endif f->fill_surface_extrusion(&surface_fill.surface, surface_fill.params, fills_by_priority[(size_t)surface_fill.params.priority]->set_entities()); +#if _DEBUG + //check no over or underextrusion if fill_exactly + if(surface_fill.params.fill_exactly && surface_fill.params.density == 1) { + ExtrusionVolume compute_volume; + ExtrusionVolume compute_volume_no_gap_fill(false); + const size_t idx_end = fills_by_priority[(size_t)surface_fill.params.priority]->entities().size(); + //check that it doesn't overextrude + for(size_t idx = idx_start; idx < idx_end; ++idx){ + fills_by_priority[(size_t)surface_fill.params.priority]->entities()[idx]->visit(compute_volume); + fills_by_priority[(size_t)surface_fill.params.priority]->entities()[idx]->visit(compute_volume_no_gap_fill); + } + assert(compute_volume.volume < unscaled(unscaled(surface_fill.surface.area())) * surface_fill.params.layer_height); + ExPolygons temp = intersection_ex(ExPolygons{surface_fill.surface.expolygon}, f->no_overlap_expolygons); + double real_surface = 0; + for(auto &t : temp) real_surface += t.area(); + assert(compute_volume.volume < unscaled(unscaled(real_surface)) * surface_fill.params.layer_height * 1.001); + assert(compute_volume.volume > unscaled(unscaled(real_surface)) * surface_fill.params.layer_height * 0.999); + } +#endif } } } diff --git a/src/libslic3r/Fill/FillConcentric.cpp b/src/libslic3r/Fill/FillConcentric.cpp index 9ea21d45ca2..a20ffa9e5e8 100644 --- a/src/libslic3r/Fill/FillConcentric.cpp +++ b/src/libslic3r/Fill/FillConcentric.cpp @@ -93,6 +93,8 @@ FillConcentricWGapFill::fill_surface_extrusion( const FillParams ¶ms, ExtrusionEntitiesPtr &out) const { + ExtrusionEntitiesPtr out_to_check; + double min_gapfill_area = double(params.flow.scaled_width()) * double(params.flow.scaled_width()); if (params.config != nullptr) min_gapfill_area = scale_d(params.config->gap_fill_min_area.get_abs_value(params.flow.width())) * double(params.flow.scaled_width()); // Perform offset. //FIXME: can miss gapfill outside of this first perimeter @@ -386,7 +388,7 @@ FillConcentricWGapFill::fill_surface_extrusion( if (!root_collection_nosort->entities().empty()) - out.push_back(root_collection_nosort); + out_to_check.push_back(root_collection_nosort); else delete root_collection_nosort; } @@ -405,9 +407,39 @@ FillConcentricWGapFill::fill_surface_extrusion( FillParams params2{ params }; params2.role = erGapFill; - do_gap_fill(intersection_ex(gapfill_areas, no_overlap_expolygons), params2, out); + do_gap_fill(intersection_ex(gapfill_areas, no_overlap_expolygons), params2, out_to_check); + } + + // check volume coverage + { + double flow_mult_exact_volume = 1; + // check if not over-extruding + if (!params.dont_adjust && params.full_infill() && !params.flow.bridge() && params.fill_exactly) { + // compute the path of the nozzle -> extruded volume + double length_tot = 0; + int nb_lines = 0; + ExtrusionVolume get_volume; + for (ExtrusionEntity *ee : out_to_check) ee->visit(get_volume); + // compute flow to remove spacing_ratio from the equation + // compute real volume to fill + double polyline_volume = compute_unscaled_volume_to_fill(surface, params); + if (get_volume.volume != 0 && polyline_volume != 0) + flow_mult_exact_volume = polyline_volume / get_volume.volume; + // failsafe, it can happen + if (flow_mult_exact_volume > 1.3) + flow_mult_exact_volume = 1.3; + if (flow_mult_exact_volume < 0.8) + flow_mult_exact_volume = 0.8; + BOOST_LOG_TRIVIAL(info) << "concentric Infill (with gapfil) process extrude " << get_volume.volume + << " mm3 for a volume of " << polyline_volume << " mm3 : we mult the flow by " + << flow_mult_exact_volume; + //apply to extrusions + ExtrusionModifyFlow modifier(flow_mult_exact_volume); + for (ExtrusionEntity *ee : out_to_check) ee->visit(modifier); + } } + out.insert(out.end(), out_to_check.begin(), out_to_check.end()); } void FillConcentric::_fill_surface_single(const FillParams ¶ms, diff --git a/src/libslic3r/Fill/FillRectilinear.cpp b/src/libslic3r/Fill/FillRectilinear.cpp index b171db95122..e21dcb5cfe6 100644 --- a/src/libslic3r/Fill/FillRectilinear.cpp +++ b/src/libslic3r/Fill/FillRectilinear.cpp @@ -3488,35 +3488,6 @@ FillRectilinearWGapFill::fill_surface_extrusion(const Surface *surface, const Fi } ExPolygons unextruded_areas; if (!polylines_rectilinear.empty()) { - double flow_mult_exact_volume = 1; - //check if not over-extruding - if (!params.dont_adjust && params.full_infill() && !params.flow.bridge() && params.fill_exactly) { - // compute the path of the nozzle -> extruded volume - double length_tot = 0; - int nb_lines = 0; - for (const Polyline &pline : polylines_rectilinear) { - Lines lines = pline.lines(); - for (auto line = lines.begin(); line != lines.end(); ++line) { - length_tot += unscaled(line->length()); - nb_lines++; - } - } - //compute flow to remove spacing_ratio from the equation - double extruded_volume = 0; - if (params.flow.spacing_ratio() < 1.f && !params.flow.bridge()) { - // the spacing is larger than usual. get the flow from the current spacing - Flow test_flow = Flow::new_from_spacing(params.flow.spacing(), params.flow.nozzle_diameter(), params.flow.height(), 1, params.flow.bridge()); - extruded_volume = test_flow.mm3_per_mm() * length_tot; - } else - extruded_volume = params.flow.mm3_per_mm() * length_tot; - // compute real volume - double polyline_volume = compute_unscaled_volume_to_fill(surface, params); - if (extruded_volume != 0 && polyline_volume != 0) flow_mult_exact_volume = polyline_volume / extruded_volume; - //failsafe, it can happen - if (flow_mult_exact_volume > 1.3) flow_mult_exact_volume = 1.3; - if (flow_mult_exact_volume < 0.8) flow_mult_exact_volume = 0.8; - BOOST_LOG_TRIVIAL(info) << "Infill (without gapfil) process extrude " << extruded_volume << " mm3 for a volume of " << polyline_volume << " mm3 : we mult the flow by " << flow_mult_exact_volume; - } //Create extrusions ExtrusionEntityCollection *eec = new ExtrusionEntityCollection(); @@ -3530,8 +3501,8 @@ FillRectilinearWGapFill::fill_surface_extrusion(const Surface *surface, const Fi extrusion_entities_append_paths( eec->set_entities(), polylines_rectilinear, good_role, - params.flow.mm3_per_mm() * params.flow_mult * flow_mult_exact_volume, - params.flow.width() * params.flow_mult * float(flow_mult_exact_volume), + params.flow.mm3_per_mm() * params.flow_mult, + params.flow.width() * params.flow_mult, params.flow.height(), !is_monotonic()); @@ -3559,6 +3530,32 @@ FillRectilinearWGapFill::fill_surface_extrusion(const Surface *surface, const Fi do_gap_fill(intersection_ex(gapfill_areas, no_overlap_expolygons), params2, coll_nosort->set_entities()); } + + // check volume coverage + { + double flow_mult_exact_volume = 1; + // check if not over-extruding + if (!params.dont_adjust && params.full_infill() && !params.flow.bridge() && params.fill_exactly) { + // compute the path of the nozzle -> extruded volume + double extruded_volume = ExtrusionVolume{}.get(*coll_nosort); + // compute flow to remove spacing_ratio from the equation + // compute real volume to fill + double polyline_volume = compute_unscaled_volume_to_fill(surface, params); + if (extruded_volume != 0 && polyline_volume != 0) + flow_mult_exact_volume = polyline_volume / extruded_volume; + // failsafe, it can happen + if (flow_mult_exact_volume > 1.3) + flow_mult_exact_volume = 1.3; + if (flow_mult_exact_volume < 0.8) + flow_mult_exact_volume = 0.8; + BOOST_LOG_TRIVIAL(info) << "rectilinear/monotonic Infill (with gapfil) process extrude " << extruded_volume + << " mm3 for a volume of " << polyline_volume << " mm3 : we mult the flow by " + << flow_mult_exact_volume; + //apply to extrusions + ExtrusionModifyFlow{flow_mult_exact_volume}.set(*coll_nosort); + } + } + // === end === if (!coll_nosort->empty()) { out.push_back(coll_nosort); diff --git a/src/libslic3r/Fill/FillSmooth.cpp b/src/libslic3r/Fill/FillSmooth.cpp index e09f6fe84ff..972e89b2c82 100644 --- a/src/libslic3r/Fill/FillSmooth.cpp +++ b/src/libslic3r/Fill/FillSmooth.cpp @@ -84,7 +84,7 @@ namespace Slic3r { } //get the flow float mult_flow = 1; - if (params.fill_exactly && idx == 0) { + if (params.fill_exactly) { // compute the volume to extrude double volume_to_occupy = compute_unscaled_volume_to_fill(&srf_to_fill, params); diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index c8a903166b0..503bb12bef1 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -884,7 +884,7 @@ void PerimeterGenerator::process() svg.draw(to_polylines(fill_no_overlap), "cyan"); svg.draw(to_polylines(not_filled_exp), "green"); svg.draw(to_polylines(last_no_gaps), "yellow"); - svg.draw(to_polylines(offset_ex(fill_clip, ext_perimeter_spacing / 2)), "brown"); + //svg.draw(to_polylines(offset_ex(surface_process_result.fill_clip, ext_perimeter_spacing / 2)), "brown"); svg.draw(to_polylines(top_infill_exp), "orange"); svg.Close(); }*/ diff --git a/tests/superslicerlibslic3r/test_fill.cpp b/tests/superslicerlibslic3r/test_fill.cpp index ce8a70f85e2..0e40309effa 100644 --- a/tests/superslicerlibslic3r/test_fill.cpp +++ b/tests/superslicerlibslic3r/test_fill.cpp @@ -5,6 +5,7 @@ #include "test_data.hpp" #include #include +#include #include #include #include @@ -209,23 +210,6 @@ TEST_CASE("Fill: Pattern Path Length") { } -class ExtrusionGetVolume : public ExtrusionVisitor { - double volume = 0; -public: - ExtrusionGetVolume() {} - void use(ExtrusionPath &path) override { - volume += unscaled(path.length()) * path.mm3_per_mm; } - void use(ExtrusionPath3D &path3D) override { volume += unscaled(path3D.length()) * path3D.mm3_per_mm; } - void use(ExtrusionMultiPath &multipath) override { for (ExtrusionPath path : multipath.paths) path.visit(*this); } - void use(ExtrusionMultiPath3D &multipath) override { for (ExtrusionPath path : multipath.paths) path.visit(*this); } - void use(ExtrusionLoop &loop) override { for (ExtrusionPath path : loop.paths) path.visit(*this); } - void use(ExtrusionEntityCollection &collection) override { for (ExtrusionEntity *entity : collection.entities()) entity->visit(*this); } - double get(ExtrusionEntityCollection &coll) { - for (ExtrusionEntity *entity : coll.entities()) entity->visit(*this); - return volume; - } -}; - TEST_CASE("Fill area: check if periemter give the good values") { Model model{}; @@ -347,6 +331,42 @@ TEST_CASE("Fill area: check if periemter give the good values") } } +void test_all(DynamicPrintConfig &config, double& extrusion_width){ + + + SECTION("45°"){ + config.set_deserialize("fill_angle", "45"); + config.set_key_value("first_layer_extrusion_width", new ConfigOptionFloatOrPercent(0.5, false)); + extrusion_width = 0.5; + //test all solid fills + SECTION("rectilinear") { config.set_key_value("bottom_fill_pattern", new ConfigOptionEnum(ipRectilinear)); } + SECTION("rectilinear with gap fill") { config.set_key_value("bottom_fill_pattern", new ConfigOptionEnum(ipRectilinearWGapFill)); } + SECTION("ipMonotonic") { config.set_key_value("bottom_fill_pattern", new ConfigOptionEnum(ipMonotonic)); } + SECTION("ipMonotonicWGapFill") { config.set_key_value("bottom_fill_pattern", new ConfigOptionEnum(ipMonotonicWGapFill)); } + SECTION("ipConcentric") { config.set_key_value("bottom_fill_pattern", new ConfigOptionEnum(ipConcentric)); } + SECTION("ipConcentricGapFill") { config.set_key_value("bottom_fill_pattern", new ConfigOptionEnum(ipConcentricGapFill)); } + SECTION("ipHilbertCurve") { config.set_key_value("bottom_fill_pattern", new ConfigOptionEnum(ipHilbertCurve)); } + SECTION("ipArchimedeanChords") { config.set_key_value("bottom_fill_pattern", new ConfigOptionEnum(ipArchimedeanChords)); } + SECTION("ipOctagramSpiral") { config.set_key_value("bottom_fill_pattern", new ConfigOptionEnum(ipOctagramSpiral)); } + SECTION("ipSmooth") { config.set_key_value("bottom_fill_pattern", new ConfigOptionEnum(ipSmooth)); } + } + SECTION("0° with bad spacing") { + config.set_deserialize("fill_angle", "0"); + config.set_key_value("first_layer_extrusion_width", new ConfigOptionFloatOrPercent(0.415, false)); + extrusion_width = 0.415; + SECTION("rectilinear") { config.set_key_value("bottom_fill_pattern", new ConfigOptionEnum(ipRectilinear)); } + SECTION("rectilinear with gap fill") { config.set_key_value("bottom_fill_pattern", new ConfigOptionEnum(ipRectilinearWGapFill)); } + SECTION("ipMonotonic") { config.set_key_value("bottom_fill_pattern", new ConfigOptionEnum(ipMonotonic)); } + SECTION("ipMonotonicWGapFill") { config.set_key_value("bottom_fill_pattern", new ConfigOptionEnum(ipMonotonicWGapFill)); } + SECTION("ipConcentric") { config.set_key_value("bottom_fill_pattern", new ConfigOptionEnum(ipConcentric)); } + SECTION("ipConcentricGapFill") { config.set_key_value("bottom_fill_pattern", new ConfigOptionEnum(ipConcentricGapFill)); } + SECTION("ipHilbertCurve") { config.set_key_value("bottom_fill_pattern", new ConfigOptionEnum(ipHilbertCurve)); } + SECTION("ipArchimedeanChords") { config.set_key_value("bottom_fill_pattern", new ConfigOptionEnum(ipArchimedeanChords)); } + SECTION("ipOctagramSpiral") { config.set_key_value("bottom_fill_pattern", new ConfigOptionEnum(ipOctagramSpiral)); } + SECTION("ipSmooth") { config.set_key_value("bottom_fill_pattern", new ConfigOptionEnum(ipSmooth)); } + } +} + #include "libslic3r/GCodeReader.hpp" TEST_CASE("Fill: extrude gcode and check it") { @@ -355,7 +375,7 @@ TEST_CASE("Fill: extrude gcode and check it") { Model model{}; TriangleMesh sample_mesh = make_cube(5, 5, 0.2); - double volume = (5 * 5 * 0.2); + const double volume = (5 * 5 * 0.2); //sample_mesh.repair(); DynamicPrintConfig &config = Slic3r::DynamicPrintConfig::full_print_config(); @@ -363,17 +383,11 @@ TEST_CASE("Fill: extrude gcode and check it") config.set_key_value("top_solid_layers", new ConfigOptionInt(1)); config.set_key_value("bottom_solid_layers", new ConfigOptionInt(1)); - config.set_key_value("enforce_full_fill_volume", new ConfigOptionBool(true)); config.set_key_value("infill_overlap", new ConfigOptionFloatOrPercent(0.1, false)); config.set_key_value("external_perimeter_overlap", new ConfigOptionPercent(100)); config.set_key_value("perimeter_overlap", new ConfigOptionPercent(100)); config.set_key_value("solid_infill_overlap", new ConfigOptionPercent(100)); - config.set_key_value("skirts", new ConfigOptionInt(0)); - - config.set_key_value("layer_height", new ConfigOptionFloat(0.2)); // get a known number of layers - config.set_key_value("first_layer_height", new ConfigOptionFloatOrPercent(0.2, false)); - config.set_key_value("extrusion_width", new ConfigOptionFloatOrPercent(0.5, false)); config.set_key_value("infill_extrusion_width", new ConfigOptionFloatOrPercent(0.5, false)); config.set_key_value("perimeter_extrusion_width", new ConfigOptionFloatOrPercent(0.5, false)); @@ -381,6 +395,25 @@ TEST_CASE("Fill: extrude gcode and check it") config.set_key_value("external_perimeter_extrusion_width", new ConfigOptionFloatOrPercent(0.5, false)); config.set_key_value("solid_infill_extrusion_width", new ConfigOptionFloatOrPercent(0.5, false)); config.set_key_value("top_infill_extrusion_width", new ConfigOptionFloatOrPercent(0.5, false)); + double extrusion_width = 0.5; + config.set_deserialize("only_one_perimeter_top", "0"); + + SECTION("classic"){ + config.set_key_value("perimeter_generator", new ConfigOptionEnum(PerimeterGeneratorType::Classic)); + test_all(config, extrusion_width); + } + SECTION("arachne"){ + config.set_key_value("perimeter_generator", new ConfigOptionEnum(PerimeterGeneratorType::Arachne)); + test_all(config, extrusion_width); + } + + + config.set_key_value("enforce_full_fill_volume", new ConfigOptionBool(true)); + config.set_key_value("skirts", new ConfigOptionInt(0)); + //simplier than auto opt = new ConfigOptionFloatsOrPercents{FloatOrPercent{0, false}}; opt.set_is_extruder_size(true); + config.set_deserialize("seam_gap", "0"); + config.set_key_value("layer_height", new ConfigOptionFloat(0.2)); // get a known number of layers + config.set_key_value("first_layer_height", new ConfigOptionFloatOrPercent(0.2, false)); auto event_counter{ 0U }; std::string stage; Print print{}; @@ -391,8 +424,8 @@ TEST_CASE("Fill: extrude gcode and check it") Slic3r::Test::gcode(gcode_filepath, print); //std::cout << "gcode generation done\n"; std::string gcode_from_file = read_to_string(gcode_filepath); - model = print.model(); - Slic3r::store_3mf("test.3mf", &model, &print.full_print_config(), OptionStore3mf{}); + // model = print.model(); + // Slic3r::store_3mf("test.3mf", &model, &print.full_print_config(), OptionStore3mf{}); //string[] lineArray = gcode_from_file GCodeReader parser; @@ -432,26 +465,26 @@ TEST_CASE("Fill: extrude gcode and check it") //std::cout << "Note that if we remove the bits of the external extrusion, it's only a volume of " << (volume - perimeterRoundGapRemove) << " that needs to be filled\n"; //std::cout << "Note that if we add the bits of the external extrusion, it's a volume of " << (volume + perimeterRoundGapAdd) << " that needs to be filled\n"; - double volumeExtrPerimeter = ExtrusionGetVolume{}.get(print.get_object(0)->get_layer(0)->regions()[0]->perimeters); - double volumeExtrInfill = ExtrusionGetVolume{}.get(print.get_object(0)->get_layer(0)->regions()[0]->fills); + double volumeExtrPerimeter = ExtrusionVolume{}.get(print.get_object(0)->get_layer(0)->regions()[0]->perimeters); + double volumeExtrInfill = ExtrusionVolume{}.get(print.get_object(0)->get_layer(0)->regions()[0]->fills); double volumeInfill = 0; for (const ExPolygon & p : print.get_object(0)->get_layer(0)->regions()[0]->fill_no_overlap_expolygons) { volumeInfill += unscaled(unscaled(p.area())); } - double spacing_diff = (0.5f - Flow::rounded_rectangle_extrusion_spacing(0.5f, 0.2f, 1.f))/2; - double raw_area_no_encroach = (5-(0.5-spacing_diff)*2) * (5-(0.5-spacing_diff)*2); - double raw_area = (5-(0.4-spacing_diff)*2) * (5-(0.4-spacing_diff)*2); + double spacing_diff = (extrusion_width - Flow::rounded_rectangle_extrusion_spacing(extrusion_width, 0.2f, 1.f))/2; + double fill_raw_area_no_encroach = (5-(extrusion_width-spacing_diff)*2) * (5-(extrusion_width-spacing_diff)*2); + double fill_raw_area = (5-(extrusion_width-0.1-spacing_diff)*2) * (5-(extrusion_width-0.1-spacing_diff)*2); - double compute_perimeter_area = 4.5*4*Flow::rounded_rectangle_extrusion_spacing(0.5f, 0.2f, 1.f); + double compute_perimeter_area = (5-extrusion_width)*4*Flow::rounded_rectangle_extrusion_spacing(extrusion_width, 0.2f, 1.f); std::cout << "area fill_no_overlap_expolygons= " << (unscaled(unscaled(print.get_object(0)->get_layer(0)->regions()[0]->fill_no_overlap_expolygons.front().contour.area()))) << "\n"; volumeInfill *= 0.2; std::cout << "\nvolumeRealr=" << (volume_perimeter_extruded + volume_infill_extruded) << " volumeRealPerimeter= " << volume_perimeter_extruded << " and volumeRealInfill=" << volume_infill_extruded << " mm3." << "\n"; std::cout << "volumeExtr=" << (volumeExtrPerimeter + volumeExtrInfill) << " volumeExtrPerimeter= " << volumeExtrPerimeter << " and volumeExtrInfill=" << volumeExtrInfill << " mm3." << "\n"; std::cout << "volumePerimeter= " << (volume - volumeInfill) << " volumePerimeter(wo/bits)= " << (volume - volumeInfill- perimeterRoundGapRemove) << " and volumeInfill=" << volumeInfill << " mm3." << "\n"; - std::cout << "volume= " << (volume) << " raw_fill_volume="<get_layer(0)->regions()[0]->fills.as_polylines(), "blue", fl.scaled_spacing()); // svg.Close(); //} - REQUIRE(abs(raw_area_no_encroach*0.2 - volumeInfill) < 0.01); + REQUIRE(abs(fill_raw_area_no_encroach*0.2 - volumeInfill) < 0.01); REQUIRE(abs(compute_perimeter_area * 0.2 - volumeExtrPerimeter) < 0.01); //std::cout << gcode_from_file; - REQUIRE(abs(volumeInfill - volumeExtrInfill) < EPSILON); + if(abs(volumeInfill - volumeExtrInfill) > EPSILON*5) // *5 for archimean chords + std::cout<<"stop"; + REQUIRE(abs(volumeInfill - volumeExtrInfill) < EPSILON * 5);// *5 for archimean chords REQUIRE(abs(volumeInfill - volume_infill_extruded) < 0.01); REQUIRE(abs((volume - volumeInfill - perimeterRoundGapRemove) - volumeExtrPerimeter) < 0.01); REQUIRE(abs((volume - volumeInfill - perimeterRoundGapRemove) - volume_perimeter_extruded) < 0.1); //there are a bit less for seam mitigation + // lower than the full volume because of the rounded extenral perimeter + REQUIRE(volume_extruded < volume); + //lower than the full volume - rounded external perimeter (because I used 4*5 as perimeter length instead of (5-offset)*4 ) + REQUIRE(volume_extruded > volume - ((5*4) * 0.2 * (0.5f-Flow::rounded_rectangle_extrusion_spacing(extrusion_width, 0.2f, 1.f))/2)); clean_file(gcode_filepath, "gcode"); } @@ -552,8 +591,8 @@ TEST_CASE("Fill: extrude gcode and check it") double perimeterRoundGapRemove = unscaled(perimeter_center_line[0].contour.length()) * 0.1*0.1 * (2 - (PI / 2)); //double perimeterRoundGapAdd = unscaled(print.get_object(0)->get_layer(0)->lslices[0].contour.length()) * 0.1*0.1 * ((PI / 2)); - double volumeExtrPerimeter = ExtrusionGetVolume{}.get(print.get_object(0)->get_layer(0)->regions()[0]->perimeters); - double volumeExtrInfill = ExtrusionGetVolume{}.get(print.get_object(0)->get_layer(0)->regions()[0]->fills); + double volumeExtrPerimeter = ExtrusionVolume{}.get(print.get_object(0)->get_layer(0)->regions()[0]->perimeters); + double volumeExtrInfill = ExtrusionVolume{}.get(print.get_object(0)->get_layer(0)->regions()[0]->fills); double volumeInfill = 0; ExPolygons infill_area = intersection_ex(print.get_object(0)->get_layer(0)->regions()[0]->fill_no_overlap_expolygons, print.get_object(0)->get_layer(0)->regions()[0]->fill_expolygons); From 3cd121dec5d9380e5bf64e4b2fe496f1b628d65f Mon Sep 17 00:00:00 2001 From: supermerill Date: Wed, 17 Jan 2024 17:05:54 +0100 Subject: [PATCH 21/25] put the layer preamble into the layer gcode pipeline, to be parsed by the cooling & other post-process --- src/libslic3r/GCode.cpp | 112 +++++++++++++++++++++++----------------- src/libslic3r/GCode.hpp | 10 ++-- 2 files changed, 72 insertions(+), 50 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index c87f6233760..dc0276fb077 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -1266,7 +1266,7 @@ std::vector sort_object_instances_by_model_order(const Pri // set standby temp for extruders // Parse the custom G-code, try to find T, and add it if not present -void GCode::_init_multiextruders(const Print& print, GCodeOutputStream& file, GCodeWriter & writer, const ToolOrdering &tool_ordering, const std::string &custom_gcode ) +void GCode::_init_multiextruders(const Print& print, std::string& out, GCodeWriter & writer, const ToolOrdering &tool_ordering, const std::string &custom_gcode ) { //set standby temp for reprap @@ -1276,9 +1276,7 @@ void GCode::_init_multiextruders(const Print& print, GCodeOutputStream& file, GC if (standby_temp > 0) { if (print.config().ooze_prevention.value) standby_temp += print.config().standby_temperature_delta.value; - file.write_format("G10 P%d R%d ; sets the standby temperature\n", - tool_id, - standby_temp); + out.append("G10 P").append(std::to_string(tool_id)).append(" R").append(std::to_string(standby_temp)).append(" ; sets the standby temperature\n"); } } } @@ -1368,6 +1366,8 @@ void GCode::_do_export(Print& print_mod, GCodeOutputStream &file, ThumbnailsGene m_pressure_equalizer = make_unique(print.config()); m_enable_extrusion_role_markers = (bool)m_pressure_equalizer; + std::string preamble_to_put_start_layer = ""; + // Write information on the generator. file.write_format("; %s\n\n", Slic3r::header_slic3r_generated().c_str()); @@ -1722,21 +1722,22 @@ void GCode::_do_export(Print& print_mod, GCodeOutputStream &file, ThumbnailsGene std::string start_all_gcode = start_gcode + "\"n" + start_filament_gcode; // Set bed temperature if the start G-code does not contain any bed temp control G-codes. if((initial_extruder_id != (uint16_t)-1) && !this->config().start_gcode_manual && this->config().gcode_flavor != gcfKlipper && print.config().first_layer_bed_temperature.get_at(initial_extruder_id) != 0) - this->_print_first_layer_bed_temperature(file, print, start_all_gcode, initial_extruder_id, false); + this->_print_first_layer_bed_temperature(preamble_to_put_start_layer, print, start_all_gcode, initial_extruder_id, false); //init extruders if (!this->config().start_gcode_manual) - this->_init_multiextruders(print, file, m_writer, tool_ordering, start_gcode); + this->_init_multiextruders(print, preamble_to_put_start_layer, m_writer, tool_ordering, start_gcode); // Set extruder(s) temperature before and after start G-code. if ((initial_extruder_id != (uint16_t)-1) && !this->config().start_gcode_manual && (this->config().gcode_flavor != gcfKlipper || print.config().start_gcode.value.empty()) && print.config().first_layer_temperature.get_at(initial_extruder_id) != 0) - this->_print_first_layer_extruder_temperatures(file, print, start_all_gcode, initial_extruder_id, false); + this->_print_first_layer_extruder_temperatures(preamble_to_put_start_layer, print, start_all_gcode, initial_extruder_id, false); // adds tag for processor - file.write_format(";%s%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role).c_str(), ExtrusionEntity::role_to_string(erCustom).c_str()); + preamble_to_put_start_layer.append(";").append(GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role)).append(ExtrusionEntity::role_to_string(erCustom)).append("\n"); // Write the custom start G-code - file.writeln(start_gcode); + preamble_to_put_start_layer.append(start_gcode).append("\n"); + m_last_pos_defined = false; //flush FanMover buffer to avoid modifying the start gcode if it's manual. @@ -1755,13 +1756,14 @@ void GCode::_do_export(Print& print_mod, GCodeOutputStream &file, ThumbnailsGene */ // Disable fan. - if ((initial_extruder_id != (uint16_t)-1) && !this->config().start_gcode_manual && print.config().disable_fan_first_layers.get_at(initial_extruder_id)) - file.write(m_writer.set_fan(uint8_t(0), initial_extruder_id)); + if ((initial_extruder_id != (uint16_t) -1) && !this->config().start_gcode_manual && print.config().disable_fan_first_layers.get_at(initial_extruder_id)) { + preamble_to_put_start_layer.append(m_writer.set_fan(uint8_t(0), initial_extruder_id)); + } print.throw_if_canceled(); // Set other general things. - file.write(this->preamble()); + preamble_to_put_start_layer.append(this->preamble()); // Calculate wiping points if needed DoExport::init_ooze_prevention(print, m_ooze_prevention); @@ -1802,17 +1804,17 @@ void GCode::_do_export(Print& print_mod, GCodeOutputStream &file, ThumbnailsGene // Set initial extruder only after custom start G-code. // Ugly hack: Do not set the initial extruder if the extruder is primed using the MMU priming towers at the edge of the print bed. if (!(has_wipe_tower && print.config().single_extruder_multi_material_priming)) { - file.write(this->set_extruder(initial_extruder_id, 0.)); + preamble_to_put_start_layer.append(this->set_extruder(initial_extruder_id, 0.)); } else { m_writer.toolchange(initial_extruder_id); } } else { // set writer to the tool as should be set in the start_gcode. - file.write(this->set_extruder(initial_extruder_id, 0., true)); + preamble_to_put_start_layer.append(this->set_extruder(initial_extruder_id, 0., true)); } } else { // if we are running a single-extruder setup, just set the extruder and "return nothing" - file.write(this->set_extruder(initial_extruder_id, 0.)); + preamble_to_put_start_layer.append(this->set_extruder(initial_extruder_id, 0.)); } } else { // the right tool should have been set by the user. @@ -1824,9 +1826,9 @@ void GCode::_do_export(Print& print_mod, GCodeOutputStream &file, ThumbnailsGene //write temps after custom gcodes to ensure the temperature are good. (after tool selection) if ((initial_extruder_id != (uint16_t)-1) && !this->config().start_gcode_manual && print.config().first_layer_temperature.get_at(initial_extruder_id) != 0) - this->_print_first_layer_extruder_temperatures(file, print, start_all_gcode, initial_extruder_id, true); + this->_print_first_layer_extruder_temperatures(preamble_to_put_start_layer, print, start_all_gcode, initial_extruder_id, true); if ((initial_extruder_id != (uint16_t)-1) && !this->config().start_gcode_manual && print.config().first_layer_bed_temperature.get_at(initial_extruder_id) != 0) - this->_print_first_layer_bed_temperature(file, print, start_all_gcode, initial_extruder_id, true); + this->_print_first_layer_bed_temperature(preamble_to_put_start_layer, print, start_all_gcode, initial_extruder_id, true); // Do all objects for each layer. if (initial_extruder_id != (uint16_t)-1) { @@ -1848,12 +1850,12 @@ void GCode::_do_export(Print& print_mod, GCodeOutputStream &file, ThumbnailsGene print.throw_if_canceled(); this->set_origin(unscale((*print_object_instance_sequential_active)->shift)); if (finished_objects > 0) { - _move_to_print_object(file, print, finished_objects, initial_extruder_id); + _move_to_print_object(preamble_to_put_start_layer, print, finished_objects, initial_extruder_id); std::string between_objects_gcode = this->placeholder_parser_process("between_objects_gcode", print.config().between_objects_gcode.value, initial_extruder_id); // Set first layer bed and extruder temperatures, don't wait for it to reach the temperature. - this->_print_first_layer_bed_temperature(file, print, between_objects_gcode, initial_extruder_id, false); - this->_print_first_layer_extruder_temperatures(file, print, between_objects_gcode, initial_extruder_id, false); - file.writeln(between_objects_gcode); + this->_print_first_layer_bed_temperature(preamble_to_put_start_layer, print, between_objects_gcode, initial_extruder_id, false); + this->_print_first_layer_extruder_temperatures(preamble_to_put_start_layer, print, between_objects_gcode, initial_extruder_id, false); + preamble_to_put_start_layer.append(between_objects_gcode).append("\n"); } else { set_extra_lift(0, 0, print.config(), m_writer, initial_extruder_id); } @@ -1866,7 +1868,8 @@ void GCode::_do_export(Print& print_mod, GCodeOutputStream &file, ThumbnailsGene // Generate G-code, run the filters (vase mode, cooling buffer), run the G-code analyser // and export G-code into file. this->process_layers(print, status_monitor, tool_ordering, collect_layers_to_print(object, status_monitor), - *print_object_instance_sequential_active - object.instances().data(), file); + *print_object_instance_sequential_active - object.instances().data(), + preamble_to_put_start_layer, file); ++finished_objects; // Flag indicating whether the nozzle temperature changes from 1st to 2nd layer were performed. // Reset it when starting another object from 1st layer. @@ -1909,13 +1912,14 @@ void GCode::_do_export(Print& print_mod, GCodeOutputStream &file, ThumbnailsGene size_t finished_objects = 1 + (it_print_object_instance - print_object_instances_ordering.begin()); if (finished_objects > 1) - _move_to_print_object(file, print, finished_objects, initial_extruder_id); + _move_to_print_object(preamble_to_put_start_layer, print, finished_objects, initial_extruder_id); assert(!object.instances().empty()); assert(*it_print_object_instance >= &*object.instances().begin() && *it_print_object_instance <= &*(object.instances().end()-1)); this->process_layers(print, status_monitor, tool_ordering, layers_to_print_range, - *it_print_object_instance - object.instances().data(), file); + *it_print_object_instance - object.instances().data(), + preamble_to_put_start_layer, file); is_layers = true; } } @@ -1977,7 +1981,7 @@ void GCode::_do_export(Print& print_mod, GCodeOutputStream &file, ThumbnailsGene // Process all layers of all objects (non-sequential mode) with a parallel pipeline: // Generate G-code, run the filters (vase mode, cooling buffer), run the G-code analyser // and export G-code into file. - this->process_layers(print, status_monitor, tool_ordering, print_object_instances_ordering, layers_to_print, file); + this->process_layers(print, status_monitor, tool_ordering, print_object_instances_ordering, layers_to_print, preamble_to_put_start_layer, file); if (m_wipe_tower) // Purge the extruder, pull out the active filament. file.write(m_wipe_tower->finalize(*this)); @@ -2083,19 +2087,17 @@ void GCode::_do_export(Print& print_mod, GCodeOutputStream &file, ThumbnailsGene print.throw_if_canceled(); } -void GCode::_move_to_print_object(GCodeOutputStream& file, const Print& print, size_t finished_objects, uint16_t initial_extruder_id) +void GCode::_move_to_print_object(std::string& gcode_out, const Print& print, size_t finished_objects, uint16_t initial_extruder_id) { // Move to the origin position for the copy we're going to print. // This happens before Z goes down to layer 0 again, so that no collision happens hopefully. m_enable_cooling_markers = false; // we're not filtering these moves through CoolingBuffer m_avoid_crossing_perimeters.use_external_mp_once(); set_extra_lift(m_last_layer_z, 0, print.config(), m_writer, initial_extruder_id); - file.write(this->retract()); - std::string gcode; + gcode_out.append(this->retract()); //go to origin of the next object (it's 0,0 because we shifted the origin to it) - Polyline polyline = this->travel_to(gcode, Point(0, 0), erTravel); - this->write_travel_to(gcode, polyline, "move to origin position for next object"); - file.write(gcode); + Polyline polyline = this->travel_to(gcode_out, Point(0, 0), erTravel); + this->write_travel_to(gcode_out, polyline, "move to origin position for next object"); m_enable_cooling_markers = true; // Disable motion planner when traveling to first object point. m_avoid_crossing_perimeters.disable_once(); @@ -2136,16 +2138,17 @@ class TBBLocalesSetter : public tbb::task_scheduler_observer // and export G-code into file. void GCode::process_layers( const Print &print, - Print::StatusMonitor &status_monitor, + Print::StatusMonitor &status_monitor, const ToolOrdering &tool_ordering, const std::vector &print_object_instances_ordering, const std::vector>> &layers_to_print, + std::string &preamble, GCodeOutputStream &output_stream) { // The pipeline is variable: The vase mode filter is optional. size_t layer_to_print_idx = 0; const auto generator = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, - [this, &print, &status_monitor, &tool_ordering, &print_object_instances_ordering, &layers_to_print, &layer_to_print_idx](tbb::flow_control& fc) -> LayerResult { + [this, &print, &status_monitor, &tool_ordering, &print_object_instances_ordering, &layers_to_print, &layer_to_print_idx, &preamble](tbb::flow_control& fc) -> LayerResult { CNumericLocalesSetter locales_setter; if (layer_to_print_idx >= layers_to_print.size()) { if ((!m_pressure_equalizer && layer_to_print_idx == layers_to_print.size()) || (m_pressure_equalizer && layer_to_print_idx == (layers_to_print.size() + 1))) { @@ -2155,7 +2158,10 @@ void GCode::process_layers( // Pressure equalizer need insert empty input. Because it returns one layer back. // Insert NOP (no operation) layer; ++layer_to_print_idx; - return LayerResult::make_nop_layer_result(); + LayerResult result = LayerResult::make_nop_layer_result(); + result.gcode = preamble; + preamble.clear(); + return result; } } else { const std::pair>& layer = layers_to_print[layer_to_print_idx++]; @@ -2163,8 +2169,12 @@ void GCode::process_layers( if (m_wipe_tower && layer_tools.has_wipe_tower) m_wipe_tower->next_layer(); print.throw_if_canceled(); - return this->process_layer(print, status_monitor, layer.second, layer_tools, &layer == &layers_to_print.back(), - &print_object_instances_ordering, size_t(-1)); + LayerResult result = this->process_layer(print, status_monitor, layer.second, layer_tools, + &layer == &layers_to_print.back(), + &print_object_instances_ordering, size_t(-1)); + result.gcode = preamble + result.gcode; + preamble.clear(); + return result; } }); const auto spiral_vase = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, @@ -2243,16 +2253,17 @@ void GCode::process_layers( // and export G-code into file. void GCode::process_layers( const Print &print, - Print::StatusMonitor &status_monitor, + Print::StatusMonitor &status_monitor, const ToolOrdering &tool_ordering, std::vector layers_to_print, const size_t single_object_idx, + std::string &preamble, GCodeOutputStream &output_stream) { // The pipeline is variable: The vase mode filter is optional. size_t layer_to_print_idx = 0; const auto generator = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, - [this, &print, &status_monitor, &tool_ordering, &layers_to_print, &layer_to_print_idx, single_object_idx](tbb::flow_control& fc) -> LayerResult { + [this, &print, &status_monitor, &tool_ordering, &layers_to_print, &layer_to_print_idx, single_object_idx, &preamble](tbb::flow_control& fc) -> LayerResult { if (layer_to_print_idx >= layers_to_print.size()) { if ((!m_pressure_equalizer && layer_to_print_idx == layers_to_print.size()) || (m_pressure_equalizer && layer_to_print_idx == (layers_to_print.size() + 1))) { fc.stop(); @@ -2261,12 +2272,21 @@ void GCode::process_layers( // Pressure equalizer need insert empty input. Because it returns one layer back. // Insert NOP (no operation) layer; ++layer_to_print_idx; - return LayerResult::make_nop_layer_result(); + LayerResult result = LayerResult::make_nop_layer_result(); + result.gcode = preamble; + preamble.clear(); + return result; } } else { LayerToPrint &layer = layers_to_print[layer_to_print_idx ++]; print.throw_if_canceled(); - return this->process_layer(print, status_monitor, { std::move(layer) }, tool_ordering.tools_for_layer(layer.print_z()), &layer == &layers_to_print.back(), nullptr, single_object_idx); + LayerResult result = this->process_layer(print, status_monitor, {std::move(layer)}, + tool_ordering.tools_for_layer(layer.print_z()), + &layer == &layers_to_print.back(), nullptr, + single_object_idx); + result.gcode = preamble + result.gcode; + preamble.clear(); + return result; } }); const auto spiral_vase = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, @@ -2524,7 +2544,7 @@ void GCode::print_machine_envelope(GCodeOutputStream &file, const Print &print) // Only do that if the start G-code does not already contain any M-code controlling an extruder temperature. // M140 - Set Bed Temperature // M190 - Set Bed Temperature and Wait -void GCode::_print_first_layer_bed_temperature(GCodeOutputStream &file, const Print &print, const std::string &gcode, uint16_t first_printing_extruder_id, bool wait) +void GCode::_print_first_layer_bed_temperature(std::string &out, const Print &print, const std::string &gcode, uint16_t first_printing_extruder_id, bool wait) { // Initial bed temperature based on the first extruder. int temp = print.config().first_layer_bed_temperature.get_at(first_printing_extruder_id); @@ -2539,7 +2559,7 @@ void GCode::_print_first_layer_bed_temperature(GCodeOutputStream &file, const Pr // the custom start G-code emited these. std::string set_temp_gcode = m_writer.set_bed_temperature(temp, wait); if ( !temp_set_by_gcode) - file.write(set_temp_gcode); + out += (set_temp_gcode); } // Write 1st layer extruder temperatures into the G-code. @@ -2547,7 +2567,7 @@ void GCode::_print_first_layer_bed_temperature(GCodeOutputStream &file, const Pr // M104 - Set Extruder Temperature // M109 - Set Extruder Temperature and Wait // RepRapFirmware: G10 Sxx -void GCode::_print_first_layer_extruder_temperatures(GCodeOutputStream &file, const Print &print, const std::string &gcode, uint16_t first_printing_extruder_id, bool wait) +void GCode::_print_first_layer_extruder_temperatures(std::string &out, const Print &print, const std::string &gcode, uint16_t first_printing_extruder_id, bool wait) { // Is the bed temperature set by the provided custom G-code? int temp_by_gcode = -1; @@ -2572,7 +2592,7 @@ void GCode::_print_first_layer_extruder_temperatures(GCodeOutputStream &file, co if (print.config().ooze_prevention.value) temp += print.config().standby_temperature_delta.value; if (temp > 0) - file.write(m_writer.set_temperature(temp, false, tool.id())); + out += (m_writer.set_temperature(temp, false, tool.id())); } } if (wait || print.config().single_extruder_multi_material.value) { @@ -2581,7 +2601,7 @@ void GCode::_print_first_layer_extruder_temperatures(GCodeOutputStream &file, co if (temp == 0) temp = print.config().temperature.get_at(first_printing_extruder_id); if (temp > 0) - file.write(m_writer.set_temperature(temp, wait, first_printing_extruder_id)); + out += (m_writer.set_temperature(temp, wait, first_printing_extruder_id)); } } } @@ -6242,7 +6262,7 @@ std::string GCode::set_extruder(uint16_t extruder_id, double print_z, bool no_to check_add_eol(gcode); } if (!no_toolchange) { - gcode+=toolchange(extruder_id, print_z); + gcode += toolchange(extruder_id, print_z); }else m_writer.toolchange(extruder_id); return gcode; } diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index ee39812c0a9..56e427b5453 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -245,8 +245,8 @@ class GCode : ExtrusionVisitorConst { GCode &m_gcodegen; }; void _do_export(Print &print, GCodeOutputStream &file, ThumbnailsGeneratorCallback thumbnail_cb); - void _move_to_print_object(GCodeOutputStream& file, const Print& print, size_t finished_objects, uint16_t initial_extruder_id); - void _init_multiextruders(const Print& print, GCodeOutputStream& file, GCodeWriter& writer, const ToolOrdering& tool_ordering, const std::string& custom_gcode); + void _move_to_print_object(std::string& gcode_out, const Print& print, size_t finished_objects, uint16_t initial_extruder_id); + void _init_multiextruders(const Print& print, std::string& gcode_out, GCodeWriter& writer, const ToolOrdering& tool_ordering, const std::string& custom_gcode); static std::vector collect_layers_to_print(const PrintObject &object, Print::StatusMonitor &status_monitor); static std::vector>> collect_layers_to_print(const Print &print, Print::StatusMonitor &status_monitor); @@ -273,6 +273,7 @@ class GCode : ExtrusionVisitorConst { const ToolOrdering &tool_ordering, const std::vector &print_object_instances_ordering, const std::vector>> &layers_to_print, + std::string &preamble, GCodeOutputStream &output_stream); // Process all layers of a single object instance (sequential mode) with a parallel pipeline: // Generate G-code, run the filters (vase mode, cooling buffer), run the G-code analyser @@ -283,6 +284,7 @@ class GCode : ExtrusionVisitorConst { const ToolOrdering &tool_ordering, std::vector layers_to_print, const size_t single_object_idx, + std::string &preamble, GCodeOutputStream &output_stream); void set_last_pos(const Point &pos) { m_last_pos = pos; m_last_pos_defined = true; } @@ -508,8 +510,8 @@ class GCode : ExtrusionVisitorConst { double_t _compute_speed_mm_per_sec(const ExtrusionPath& path, double speed = -1); std::string _after_extrude(const ExtrusionPath &path); void print_machine_envelope(GCodeOutputStream &file, const Print &print); - void _print_first_layer_bed_temperature(GCodeOutputStream &file, const Print &print, const std::string &gcode, uint16_t first_printing_extruder_id, bool wait); - void _print_first_layer_extruder_temperatures(GCodeOutputStream &file, const Print &print, const std::string &gcode, uint16_t first_printing_extruder_id, bool wait); + void _print_first_layer_bed_temperature(std::string &out, const Print &print, const std::string &gcode, uint16_t first_printing_extruder_id, bool wait); + void _print_first_layer_extruder_temperatures(std::string &out, const Print &print, const std::string &gcode, uint16_t first_printing_extruder_id, bool wait); // On the first printing layer. This flag triggers first layer speeds. bool on_first_layer() const { return m_layer != nullptr && m_layer->id() == 0; } // To control print speed of 1st object layer over raft interface. From 59421d0a78e0c50e53d9bb0be38b0a5538ee2840 Mon Sep 17 00:00:00 2001 From: supermerill Date: Thu, 18 Jan 2024 15:49:54 +0100 Subject: [PATCH 22/25] fan mover: little fix, began test cases --- src/libslic3r/GCode/FanMover.cpp | 14 +- src/libslic3r/GCode/FanMover.hpp | 4 +- tests/superslicerlibslic3r/CMakeLists.txt | 1 + tests/superslicerlibslic3r/test_fan_mover.cpp | 282 ++++++++++++++++++ 4 files changed, 293 insertions(+), 8 deletions(-) create mode 100644 tests/superslicerlibslic3r/test_fan_mover.cpp diff --git a/src/libslic3r/GCode/FanMover.cpp b/src/libslic3r/GCode/FanMover.cpp index 159d13c293e..b108bbc459a 100644 --- a/src/libslic3r/GCode/FanMover.cpp +++ b/src/libslic3r/GCode/FanMover.cpp @@ -1,6 +1,7 @@ #include "FanMover.hpp" #include "GCodeReader.hpp" +#include "LocalesUtils.hpp" #include /* @@ -66,16 +67,12 @@ float get_axis_value(const std::string& line, char axis) void change_axis_value(std::string& line, char axis, const float new_value, const int decimal_digits) { - - std::ostringstream ss; - ss << std::fixed << std::setprecision(decimal_digits) << new_value; - char match[3] = " X"; match[1] = axis; size_t pos = line.find(match) + 2; size_t end = std::min(line.find(' ', pos + 1), line.find(';', pos + 1)); - line = line.replace(pos, end - pos, ss.str()); + line = line.replace(pos, end - pos, to_string_nozero(new_value, decimal_digits)); } int16_t get_fan_speed(const std::string &line, GCodeFlavor flavor) { @@ -213,7 +210,10 @@ void FanMover::_remove_slow_fan(int16_t min_speed, float past_sec) { std::string FanMover::_set_fan(int16_t speed) { const Tool* tool = m_writer.get_tool(m_currrent_extruder < 20 ? m_currrent_extruder : 0); - return GCodeWriter::set_fan(m_writer.config.gcode_flavor.value, m_writer.config.gcode_comments.value, speed, tool ? tool->fan_offset() : 0, m_writer.config.fan_percentage.value); + std::string str = GCodeWriter::set_fan(m_writer.config.gcode_flavor.value, m_writer.config.gcode_comments.value, speed, tool ? tool->fan_offset() : 0, m_writer.config.fan_percentage.value); + if(!str.empty() && str.back() == '\n') + return str.substr(0,str.size()-1); + return str; } @@ -491,9 +491,11 @@ void FanMover::_process_gcode_line(GCodeReader& reader, const GCodeReader::GCode remove_from_buffer(m_buffer.begin()); } } +#if _DEBUG double sum = 0; for (auto& data : m_buffer) sum += data.time; assert( std::abs(m_buffer_time_size - sum) < 0.01); +#endif } } // namespace Slic3r diff --git a/src/libslic3r/GCode/FanMover.hpp b/src/libslic3r/GCode/FanMover.hpp index f785e4c658a..2d0c3ad6306 100644 --- a/src/libslic3r/GCode/FanMover.hpp +++ b/src/libslic3r/GCode/FanMover.hpp @@ -48,8 +48,8 @@ class FanMover uint16_t m_currrent_extruder = 0; // variable for when you add a line (front of the buffer) - int m_front_buffer_fan_speed = 0; - int m_back_buffer_fan_speed = 0; + int m_front_buffer_fan_speed = 1; + int m_back_buffer_fan_speed = 1; BufferData m_current_kickstart{"",-1,0}; //buffer diff --git a/tests/superslicerlibslic3r/CMakeLists.txt b/tests/superslicerlibslic3r/CMakeLists.txt index 63d0f96d2f1..2d992de4f3f 100644 --- a/tests/superslicerlibslic3r/CMakeLists.txt +++ b/tests/superslicerlibslic3r/CMakeLists.txt @@ -20,6 +20,7 @@ create_test(test_clipper_utils) create_test(test_dense_infill) create_test(test_denserinfill) create_test(test_extrusion_entity) +create_test(test_fan_mover) create_test(test_fill) create_test(test_flow) create_test(test_gcodewriter) diff --git a/tests/superslicerlibslic3r/test_fan_mover.cpp b/tests/superslicerlibslic3r/test_fan_mover.cpp new file mode 100644 index 00000000000..ac9720176ad --- /dev/null +++ b/tests/superslicerlibslic3r/test_fan_mover.cpp @@ -0,0 +1,282 @@ + +//#define CATCH_CONFIG_DISABLE + +#include +#include "test_data.hpp" +#include +#include + +#include + +using namespace Slic3r; +using namespace Slic3r::Geometry; +using namespace Slic3r::Test; + +// note: F600: 10mm/s + +TEST_CASE("Simple gcode") { + + GCodeWriter writer; + //what's used from the writer: + writer.config.gcode_flavor.value = gcfMarlinFirmware; + writer.config.gcode_comments.value = false; + writer.config.fan_percentage.value = false; //0 -> 255 + //writer.tool[0] = nullptr; + assert(writer.tool() == nullptr); + assert(writer.get_tool(0) == nullptr); + + const std::string gcode = []() { + std::string gcode; + gcode += "M107\n"; + gcode += "G1 X0 Y0 F600\n"; // shouldn't move + gcode += "G1 X20 Y0 E20\n"; // 2 sec + gcode += "M106 S153\n"; // activate at 60% + gcode += "G1 X40 Y0 E20\n"; // 2sec + gcode += "M107\n"; // disable + gcode += "G1 X60 Y0 E20\n"; // 2sec + return gcode; + }(); + + SECTION("disable evrything") + { + Slic3r::FanMover fan_mover(writer, + 0, // fan_speedup_time.value, + false, // with_D_option + true, // use_relative_e_distances.value, + false, // fan_speedup_overhangs.value, + 0 // fan_kickstart.value)); + ); + std::string processed_gcode = fan_mover.process_gcode(gcode, true); + REQUIRE(gcode == processed_gcode); + } + + SECTION("only kickstart 1sec") + { + Slic3r::FanMover fan_mover(writer, + 0, // fan_speedup_time.value, + false, // with_D_option + true, // use_relative_e_distances.value, + false, // fan_speedup_overhangs.value, + 1 // fan_kickstart.value)); + ); + const std::string processed_gcode = fan_mover.process_gcode(gcode, true); + std::string wanted_gcode; + wanted_gcode += "M107\n"; + wanted_gcode += "G1 X0 Y0 F600\n"; //shouldn't move + wanted_gcode += "G1 X20 Y0 E20\n"; // 2 sec + wanted_gcode += "M106 S255\n"; //activate with kickstart + wanted_gcode += "G1 X26 Y0 E6\n"; // 1*0.6 = 0.6sec + wanted_gcode += "M106 S153\n"; //go to good speed 60% of 1 second + wanted_gcode += "G1 X40 Y0 E14\n"; // 2 - 1*0.6 = 1.4sec + wanted_gcode += "M107\n"; //disable + wanted_gcode += "G1 X60 Y0 E20\n"; // 2sec + REQUIRE(wanted_gcode == processed_gcode); + } + + SECTION("only speedup 1sec") + { + Slic3r::FanMover fan_mover(writer, + 1, // fan_speedup_time.value, + false, // with_D_option + true, // use_relative_e_distances.value, + false, // fan_speedup_overhangs.value, + 0 // fan_kickstart.value)); + ); + std::string processed_gcode = fan_mover.process_gcode(gcode, true); + std::string wanted_gcode; + wanted_gcode += "M107\n"; + wanted_gcode += "G1 X0 Y0 F600\n"; //shouldn't move + wanted_gcode += "G1 X10 Y0 E10\n"; // 1 sec + wanted_gcode += "M106 S153\n"; //activate + wanted_gcode += "G1 X20 Y0 E10\n"; // 1 sec + wanted_gcode += "G1 X40 Y0 E20\n"; // 2sec + wanted_gcode += "M107\n"; //disable + wanted_gcode += "G1 X60 Y0 E20\n"; // 2sec + REQUIRE(wanted_gcode == processed_gcode); + } + + SECTION("speedup deactivated on not-overhangs") + { + Slic3r::FanMover fan_mover(writer, + 1, // fan_speedup_time.value, + false, // with_D_option + true, // use_relative_e_distances.value, + true, // fan_speedup_overhangs.value, + 0 // fan_kickstart.value)); + ); + std::string type_not_overhang; + SECTION("erNone") { type_not_overhang = std::string(";TYPE:") + ExtrusionEntity::role_to_string(ExtrusionRole::erNone) + "\n"; } + SECTION("erPerimeter") { type_not_overhang = std::string(";TYPE:") + ExtrusionEntity::role_to_string(ExtrusionRole::erPerimeter) + "\n"; } + SECTION("erExternalPerimeter") { type_not_overhang = std::string(";TYPE:") + ExtrusionEntity::role_to_string(ExtrusionRole::erExternalPerimeter) + "\n"; } + SECTION("erInternalInfill") { type_not_overhang = std::string(";TYPE:") + ExtrusionEntity::role_to_string(ExtrusionRole::erInternalInfill) + "\n"; } + SECTION("erSolidInfill") { type_not_overhang = std::string(";TYPE:") + ExtrusionEntity::role_to_string(ExtrusionRole::erSolidInfill) + "\n"; } + SECTION("erTopSolidInfill") { type_not_overhang = std::string(";TYPE:") + ExtrusionEntity::role_to_string(ExtrusionRole::erTopSolidInfill) + "\n"; } + SECTION("erBridgeInfill") { type_not_overhang = std::string(";TYPE:") + ExtrusionEntity::role_to_string(ExtrusionRole::erBridgeInfill) + "\n"; } //note: bridge infill isn't overhang + SECTION("erInternalBridgeInfill") { type_not_overhang = std::string(";TYPE:") + ExtrusionEntity::role_to_string(ExtrusionRole::erInternalBridgeInfill) + "\n"; } + SECTION("erThinWall") { type_not_overhang = std::string(";TYPE:") + ExtrusionEntity::role_to_string(ExtrusionRole::erThinWall) + "\n"; } + SECTION("erGapFill") { type_not_overhang = std::string(";TYPE:") + ExtrusionEntity::role_to_string(ExtrusionRole::erGapFill) + "\n"; } + SECTION("erSkirt") { type_not_overhang = std::string(";TYPE:") + ExtrusionEntity::role_to_string(ExtrusionRole::erSkirt) + "\n"; } + SECTION("erSupportMaterial") { type_not_overhang = std::string(";TYPE:") + ExtrusionEntity::role_to_string(ExtrusionRole::erSupportMaterial) + "\n"; } + SECTION("erSupportMaterialInterface") { type_not_overhang = std::string(";TYPE:") + ExtrusionEntity::role_to_string(ExtrusionRole::erSupportMaterialInterface) + "\n"; } + SECTION("erWipeTower") { type_not_overhang = std::string(";TYPE:") + ExtrusionEntity::role_to_string(ExtrusionRole::erWipeTower) + "\n"; } + SECTION("erMilling") { type_not_overhang = std::string(";TYPE:") + ExtrusionEntity::role_to_string(ExtrusionRole::erMilling) + "\n"; } + SECTION("erCustom") { type_not_overhang = std::string(";TYPE:") + ExtrusionEntity::role_to_string(ExtrusionRole::erCustom) + "\n"; } + SECTION("erMixed") { type_not_overhang = std::string(";TYPE:") + ExtrusionEntity::role_to_string(ExtrusionRole::erMixed) + "\n"; } + SECTION("erTravel") { type_not_overhang = std::string(";TYPE:") + ExtrusionEntity::role_to_string(ExtrusionRole::erTravel) + "\n"; } + std::string processed_gcode = fan_mover.process_gcode(type_not_overhang + gcode, true); + REQUIRE(type_not_overhang + gcode == processed_gcode); + } + SECTION("speedup activated on overhangs") + { + Slic3r::FanMover fan_mover(writer, + 1, // fan_speedup_time.value, + false, // with_D_option + true, // use_relative_e_distances.value, + true, // fan_speedup_overhangs.value, + 0 // fan_kickstart.value)); + ); + std::string type_overhang; + SECTION("erOverhangPerimeter") { type_overhang = std::string(";TYPE:") + ExtrusionEntity::role_to_string(ExtrusionRole::erOverhangPerimeter) + "\n"; } + std::string processed_gcode = fan_mover.process_gcode(type_overhang + gcode, true); + std::string wanted_gcode; + wanted_gcode += "M107\n"; + wanted_gcode += "G1 X0 Y0 F600\n"; //shouldn't move + wanted_gcode += "G1 X10 Y0 E10\n"; // 1 sec + wanted_gcode += "M106 S153\n"; //activate + wanted_gcode += "G1 X20 Y0 E10\n"; // 1 sec + wanted_gcode += "G1 X40 Y0 E20\n"; // 2sec + wanted_gcode += "M107\n"; //disable + wanted_gcode += "G1 X60 Y0 E20\n"; // 2sec + REQUIRE(type_overhang + wanted_gcode == processed_gcode); + } + + SECTION("erase double M107") + { + Slic3r::FanMover fan_mover(writer, + 0, // fan_speedup_time.value, + false, // with_D_option + true, // use_relative_e_distances.value, + false, // fan_speedup_overhangs.value, + 0 // fan_kickstart.value)); + ); + std::string m107 = "M107\n"; + std::string processed_gcode = fan_mover.process_gcode(m107+gcode+m107, false); + processed_gcode += fan_mover.process_gcode(gcode+m107, true); + REQUIRE(gcode+gcode.substr(5) == processed_gcode); // substr to remove first m107 + } + SECTION("erase M107-like M106 -> M107") + { + Slic3r::FanMover fan_mover(writer, + 0, // fan_speedup_time.value, + false, // with_D_option + true, // use_relative_e_distances.value, + false, // fan_speedup_overhangs.value, + 0 // fan_kickstart.value)); + ); + std::string m106 = "M106 S0\n"; + std::string processed_gcode = fan_mover.process_gcode(gcode+m106, false); + processed_gcode += fan_mover.process_gcode(gcode, true); + REQUIRE(gcode+gcode.substr(5) == processed_gcode); // substr to remove first m107 + } + //TODO? + //SECTION("erase M106 -> M107") + //{ + // Slic3r::FanMover fan_mover(writer, + // 0, // fan_speedup_time.value, + // false, // with_D_option + // true, // use_relative_e_distances.value, + // false, // fan_speedup_overhangs.value, + // 0 // fan_kickstart.value)); + // ); + // std::string m106 = "M106 S125\n"; + // std::string processed_gcode = fan_mover.process_gcode(m106+gcode+m106, false); + // processed_gcode += fan_mover.process_gcode(gcode, true); + // REQUIRE(gcode+m106 == processed_gcode); // substr to remove first m107 + //} +} + + +TEST_CASE("Simple gcode (absoute)") +{ + GCodeWriter writer; + // what's used from the writer: + writer.config.gcode_flavor.value = gcfMarlinFirmware; + writer.config.gcode_comments.value = false; + writer.config.fan_percentage.value = false; // 0 -> 255 + // writer.tool[0] = nullptr; + assert(writer.tool() == nullptr); + assert(writer.get_tool(0) == nullptr); + + const std::string gcode = []() { + std::string gcode; + gcode += "M107\n"; + gcode += "G1 X0 Y0 F600\n"; // shouldn't move + gcode += "G1 X20 Y0 E20\n"; // 2 sec + gcode += "M106 S153\n"; // activate at 60% + gcode += "G1 X40 Y0 E40\n"; // 2sec + gcode += "M107\n"; // disable + gcode += "G1 X60 Y0 E60\n"; // 2sec + return gcode; + }(); + + + SECTION("disable evrything") + { + Slic3r::FanMover fan_mover(writer, + 0, // fan_speedup_time.value, + false, // with_D_option + false, // use_relative_e_distances.value, + false, // fan_speedup_overhangs.value, + 0 // fan_kickstart.value)); + ); + std::string processed_gcode = fan_mover.process_gcode(gcode, true); + REQUIRE(gcode == processed_gcode); + } + + SECTION("only kickstart 1sec") + { + Slic3r::FanMover fan_mover(writer, + 0, // fan_speedup_time.value, + false, // with_D_option + false, // use_relative_e_distances.value, + false, // fan_speedup_overhangs.value, + 1 // fan_kickstart.value)); + ); + const std::string processed_gcode = fan_mover.process_gcode(gcode, true); + std::string wanted_gcode; + wanted_gcode += "M107\n"; + wanted_gcode += "G1 X0 Y0 F600\n"; //shouldn't move + wanted_gcode += "G1 X20 Y0 E20\n"; // 2 sec + wanted_gcode += "M106 S255\n"; //activate with kickstart + wanted_gcode += "G1 X26 Y0 E26\n"; // 1*0.6 = 0.6sec + wanted_gcode += "M106 S153\n"; //go to good speed 60% of 1 second + wanted_gcode += "G1 X40 Y0 E40\n"; // 2 - 1*0.6 = 1.4sec + wanted_gcode += "M107\n"; //disable + wanted_gcode += "G1 X60 Y0 E60\n"; // 2sec + REQUIRE(wanted_gcode == processed_gcode); + } + + SECTION("only speedup 1sec") + { + Slic3r::FanMover fan_mover(writer, + 1, // fan_speedup_time.value, + false, // with_D_option + false, // use_relative_e_distances.value, + false, // fan_speedup_overhangs.value, + 0 // fan_kickstart.value)); + ); + std::string processed_gcode = fan_mover.process_gcode(gcode, true); + std::string wanted_gcode; + wanted_gcode += "M107\n"; + wanted_gcode += "G1 X0 Y0 F600\n"; //shouldn't move + wanted_gcode += "G1 X10 Y0 E10\n"; // 1 sec + wanted_gcode += "M106 S153\n"; //activate + wanted_gcode += "G1 X20 Y0 E20\n"; // 1 sec + wanted_gcode += "G1 X40 Y0 E40\n"; // 2sec + wanted_gcode += "M107\n"; //disable + wanted_gcode += "G1 X60 Y0 E60\n"; // 2sec + REQUIRE(wanted_gcode == processed_gcode); + } +} + +//TODO: complex gcode From e0f74892b5cefa06c41ef9657794eedcb8e53b28 Mon Sep 17 00:00:00 2001 From: supermerill Date: Wed, 17 Jan 2024 17:35:17 +0100 Subject: [PATCH 23/25] Check for fimware compatibility with M73 & M117 (warning) Don't print M117 for pause/color if firmware not compatible. --- src/libslic3r/GCode.cpp | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index dc0276fb077..d8994c9759e 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -855,6 +855,25 @@ namespace DoExport { } } // namespace DoExport + +void check_remaning_times(GCodeFlavor firmware, RemainingTimeType type, Print::StatusMonitor &monitor) +{ + if (type == RemainingTimeType::rtM73 || type == rtM73_M117 || type == rtM73_Quiet) { + if (!(firmware == gcfMarlinLegacy || firmware == gcfMarlinFirmware || firmware == gcfMakerWare || + firmware == gcfKlipper || firmware == gcfRepRap)) + monitor.active_step_add_warning( + PrintStateBase::WarningLevel::CRITICAL, + _(L("Your firmware doesn't allow to print the remaining times with M73."))); + } + if ((type == rtM117 || type == rtM73_M117)) { + if (!(firmware == gcfMarlinLegacy || firmware == gcfMarlinFirmware || firmware == gcfMakerWare || + firmware == gcfKlipper || firmware == gcfRepRap || firmware == gcfRepetier || + firmware == gcfSmoothie)) + monitor.active_step_add_warning( + PrintStateBase::WarningLevel::CRITICAL, + _(L("Your firmware doesn't allow to print the remaining times with M117."))); + } +} void GCode::do_export(Print* print, const char* path, GCodeProcessorResult* result, ThumbnailsGeneratorCallback thumbnail_cb) { PROFILE_CLEAR(); @@ -894,6 +913,9 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessorResult* resu GCodeOutputStream file(boost::nowide::fopen(path_tmp.c_str(), "wb"), m_processor, *this); if (! file.is_open()) throw Slic3r::RuntimeError(std::string("G-code export to ") + path + " failed.\nCannot open the file for writing.\n"); + + if(print->config().remaining_times) + check_remaning_times(print->config().gcode_flavor, print->config().remaining_times_type, monitor); try { m_placeholder_parser.reset(); @@ -2733,7 +2755,9 @@ std::string emit_custom_gcode_per_print_z( cfg.set_key_value("color_change_extruder", new ConfigOptionInt(m600_extruder_before_layer)); gcode += gcodegen.placeholder_parser_process("pause_print_gcode", GCodeWriter::get_default_pause_gcode(print.config()), current_extruder_id, &cfg); gcode += "\n"; - gcode += "M117 Change filament for Extruder " + std::to_string(m600_extruder_before_layer) + "\n"; + if (auto flavor = print.config().gcode_flavor.value; + flavor == gcfKlipper || flavor == gcfLerdge || flavor == gcfMarlinFirmware || flavor == gcfMarlinLegacy || flavor == gcfRepetier || flavor == gcfSmoothie || flavor == gcfRepRap) + gcode += "M117 Change filament for Extruder " + std::to_string(m600_extruder_before_layer) + "\n"; } else { if (GCodeWriter::get_default_color_change_gcode(print.config()).empty()) { @@ -2765,7 +2789,9 @@ std::string emit_custom_gcode_per_print_z( gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Pause_Print) + "\n"; //! FIXME_in_fw show message during print pause if (!pause_print_msg.empty()) - gcode += "M117 " + pause_print_msg + "\n"; + if (auto flavor = print.config().gcode_flavor.value; + flavor == gcfKlipper || flavor == gcfLerdge || flavor == gcfMarlinFirmware || flavor == gcfMarlinLegacy || flavor == gcfRepetier || flavor == gcfSmoothie || flavor == gcfRepRap) + gcode += "M117 " + pause_print_msg + "\n"; gcode += gcodegen.placeholder_parser_process("pause_print_gcode", GCodeWriter::get_default_pause_gcode(print.config()), current_extruder_id); } else { // add tag for processor From 1fb8127c490f47e0fbb2029f60f39f6b3f76d101 Mon Sep 17 00:00:00 2001 From: supermerill Date: Wed, 17 Jan 2024 19:31:41 +0100 Subject: [PATCH 24/25] revert 0a65e1 as it's fixed in the gcodeviewer / processor directly (by prusa i think) supermerill/SuperSlicer#1076 --- src/libslic3r/Fill/Fill.cpp | 2 +- src/slic3r/GUI/GUI_Preview.cpp | 18 ------------------ 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index ea695fefac3..7b01ddefe73 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -692,10 +692,10 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive: fills_by_priority[(size_t)surface_fill.params.priority]->entities()[idx]->visit(compute_volume); fills_by_priority[(size_t)surface_fill.params.priority]->entities()[idx]->visit(compute_volume_no_gap_fill); } - assert(compute_volume.volume < unscaled(unscaled(surface_fill.surface.area())) * surface_fill.params.layer_height); ExPolygons temp = intersection_ex(ExPolygons{surface_fill.surface.expolygon}, f->no_overlap_expolygons); double real_surface = 0; for(auto &t : temp) real_surface += t.area(); + assert(compute_volume.volume < unscaled(unscaled(surface_fill.surface.area())) * surface_fill.params.layer_height + EPSILON); assert(compute_volume.volume < unscaled(unscaled(real_surface)) * surface_fill.params.layer_height * 1.001); assert(compute_volume.volume > unscaled(unscaled(real_surface)) * surface_fill.params.layer_height * 0.999); } diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 2bd179abeea..1f4fe58a5c1 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -630,13 +630,6 @@ wxBoxSizer* Preview::create_layers_slider_sizer() Bind(DoubleSlider::wxCUSTOMEVT_TICKSCHANGED, [this](wxEvent&) { Model& model = wxGetApp().plater()->model(); Info custom_gcode_per_print_z = m_layers_slider->GetTicksValues(); - //remove z-shift from gcode output - const float z_shift = wxGetApp().preset_bundle->printers.get_edited_preset().config.opt_float("z_offset"); - if (can_display_gcode() && z_shift != 0 && ForceState::ForceExtrusions != current_force_state) { - for (CustomGCode::Item& tick : custom_gcode_per_print_z.gcodes) { - tick.print_z -= z_shift; - } - } model.custom_gcode_per_print_z = custom_gcode_per_print_z; m_schedule_background_process(); @@ -718,17 +711,6 @@ void Preview::update_layers_slider(const std::vector& layers_z, bool kee ticks_info_from_model.mode = CustomGCode::Mode::SingleExtruder; ticks_info_from_model.gcodes = m_canvas->get_custom_gcode_per_print_z(); } - // Add offset from printer z offset - if (wxGetApp().preset_bundle && wxGetApp().preset_bundle->printers.get_edited_preset().config.option("z_offset")) - { - //add z-shift from gcode output - const float z_shift = wxGetApp().preset_bundle->printers.get_edited_preset().config.opt_float("z_offset"); - if (can_display_gcode() && z_shift != 0 && ForceState::ForceExtrusions != current_force_state) { - for (CustomGCode::Item& tick : ticks_info_from_model.gcodes) { - tick.print_z += z_shift; - } - } - } //check incoherencies check_layers_slider_values(ticks_info_from_model.gcodes, layers_z); From f83cd4b87a5bdf9976fa740bdd7484fc422971e0 Mon Sep 17 00:00:00 2001 From: supermerill Date: Thu, 18 Jan 2024 13:26:03 +0100 Subject: [PATCH 25/25] Bed texture fixes: . if vendor has only texture or model, still show it. . png texture can turn black on compression on soe hardware. A new preference (compress_png_texture) is now available to disable the optimisation that can cause that. You have to relaunch the app to force the reload of the texture or: remove it, go to platter, then re-add it. --- src/libslic3r/AppConfig.cpp | 3 +++ src/slic3r/GUI/3DBed.cpp | 9 +++++++-- src/slic3r/GUI/Preferences.cpp | 7 +++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp index ae0c883fb8f..75e7b1080b9 100644 --- a/src/libslic3r/AppConfig.cpp +++ b/src/libslic3r/AppConfig.cpp @@ -361,6 +361,9 @@ void AppConfig::set_defaults() set("check_blacklisted_library", "1"); #endif // _WIN32 + if (get("compress_png_texture").empty()) + set("compress_png_texture", "1"); + // remove old 'use_legacy_opengl' parameter from this config, if present if (!get("use_legacy_opengl").empty()) erase("", "use_legacy_opengl"); diff --git a/src/slic3r/GUI/3DBed.cpp b/src/slic3r/GUI/3DBed.cpp index a263dd8c49a..6bd072654fd 100644 --- a/src/slic3r/GUI/3DBed.cpp +++ b/src/slic3r/GUI/3DBed.cpp @@ -392,6 +392,10 @@ std::tuple Bed3D::detect_type(const std::string texture_filename = PresetUtils::system_printer_bed_texture(*curr); if (!model_filename.empty() && !texture_filename.empty()) return { Type::System, model_filename, texture_filename, PresetUtils::system_printer_model(*curr)->bed_with_grid }; + else if(!model_filename.empty()) + return { Type::System, model_filename, {}, true }; + else if(!texture_filename.empty()) + return { Type::System, {}, texture_filename, PresetUtils::system_printer_model(*curr)->bed_with_grid}; } } @@ -452,7 +456,7 @@ void Bed3D::render_texture(bool bottom, GLCanvas3D& canvas) const } else if (boost::algorithm::iends_with(texture_absolute_filename, ".png")) { // generate a temporary lower resolution texture to show while no main texture levels have been compressed - if (temp_texture->get_id() == 0 || temp_texture->get_source() != texture_absolute_filename) { + if (wxGetApp().app_config->get("compress_png_texture") == "1" && (temp_texture->get_id() == 0 || temp_texture->get_source() != texture_absolute_filename)) { if (!temp_texture->load_from_file(texture_absolute_filename, false, GLTexture::None, false)) { render_default(bottom, false); return; @@ -461,7 +465,8 @@ void Bed3D::render_texture(bool bottom, GLCanvas3D& canvas) const } // starts generating the main texture, compression will run asynchronously - if (!texture->load_from_file(texture_absolute_filename, true, GLTexture::MultiThreaded, true)) { + if (!texture->load_from_file(texture_absolute_filename, true, + wxGetApp().app_config->get("compress_png_texture") == "1" ? GLTexture::MultiThreaded : GLTexture::ECompressionType::None, true)) { render_default(bottom, false); return; } diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index ab6039ff013..6da31dc9110 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -480,6 +480,13 @@ void PreferencesDialog::build(size_t selected_tab) m_optgroup_camera->append_single_option_line(option); #endif // _WIN32 || __APPLE__ + def.label = L("Compress png textures"); + def.type = coBool; + def.tooltip = L("If your custom texture (in png format) is displayed black, then disable this option to remove the problematic optimisation."); + def.set_default_value(new ConfigOptionBool{ app_config->get("compress_png_texture") == "1" }); + option = Option(def, "compress_png_texture"); + m_optgroup_camera->append_single_option_line(option); + activate_options_tab(m_optgroup_camera); // Add "GUI" tab