///|/ Copyright (c) Prusa Research 2024 Filip Sykala @Jony01 ///|/ ///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher ///|/ #ifndef SLA_SUPPORTPOINTGENERATOR_HPP #define SLA_SUPPORTPOINTGENERATOR_HPP #include #include #include #include "libslic3r/Point.hpp" #include "libslic3r/ExPolygon.hpp" #include "libslic3r/SLA/SupportPoint.hpp" #include "libslic3r/SLA/SupportIslands/SampleConfig.hpp" #include "libslic3r/SLA/SupportIslands/SampleConfigFactory.hpp" namespace Slic3r::sla { /// /// Configuration for automatic support placement /// struct SupportPointGeneratorConfig{ /// /// 0 mean only one support point for each island /// lower than one mean less amount of support points /// 1 mean fine tuned sampling /// more than one mean bigger amout of support points /// float density_relative{1.f}; /// /// Size range for support point interface (head) /// float head_diameter = 0.4f; // [in mm] // FIXME: calculate actual pixel area from printer config: // const float pixel_area = // pow(wxGetApp().preset_bundle->project_config.option("display_width") / // wxGetApp().preset_bundle->project_config.option("display_pixels_x"), 2.f); // // Minimal island Area to print - TODO: Should be modifiable from UI // !! Filter should be out of sampling algorithm !! float minimal_island_area = pow(0.047f, 2.f); // [in mm^2] pixel_area // maximal distance to nearest support point(define radiuses per layer) // x axis .. mean distance on layer(XY) // y axis .. mean difference of height(Z) // Points of lines [in mm] std::vector support_curve; // Configuration for sampling island SampleConfig island_configuration = SampleConfigFactory::create(head_diameter); }; struct LayerPart; // forward decl. using LayerParts = std::vector; struct PartLink { LayerParts::const_iterator part_it; // float overlap_area; // sum of overlap areas // ExPolygons overlap; // clipper intersection_ex // ExPolygons overhang; // clipper diff_ex }; #ifdef NDEBUG // In release mode, use the optimized container. using PartLinks = boost::container::small_vector; #else // In debug mode, use the standard vector, which is well handled by debugger visualizer. using PartLinks = std::vector; #endif // Part on layer is defined by its shape struct LayerPart { // Pointer to expolygon stored in input const ExPolygon *shape; // rectangular bounding box of shape BoundingBox shape_extent; // uniformly sampled shape contour Slic3r::Points samples; // IMPROVE: sample only overhangs part of shape // Parts from previous printed layer, which is connected to current part PartLinks prev_parts; PartLinks next_parts; }; /// /// Extend support point with information from layer /// struct LayerSupportPoint: public SupportPoint { // Pointer on source ExPolygon otherwise nullptr //const LayerPart *part{nullptr}; // 2d coordinate on layer // use only when part is not nullptr Point position_on_layer; // [scaled_ unit] // 2d direction into expolygon mass // used as ray to positioning 3d point on mesh surface // Island has direction [0,0] - should be placed on surface from bottom Point direction_to_mass; // index into curve to faster found radius for current layer size_t radius_curve_index = 0; coord_t current_radius = 0; // [in scaled mm] // information whether support point is active in current investigated layer // Flagged false when no part on layer in Radius 'r' around support point // Tool to support overlapped overhang area multiple times bool active_in_part = true; }; using LayerSupportPoints = std::vector; /// /// One slice divided into /// struct Layer { // Absolute distance from Zero - copy value from heights float print_z; // [in mm] // data for one expolygon LayerParts parts; }; using Layers = std::vector; /// /// Keep state of Support Point generation /// Used for resampling with different configuration /// struct SupportPointGeneratorData { // Input slices of mesh std::vector slices; // Keep information about layer and its height // and connection between layers for its part // NOTE: contain links into slices Layers layers; }; // call during generation of support points to check cancel event using ThrowOnCancel = std::function; // call to say progress of generation into gui in range from 0 to 100 using StatusFunction= std::function; /// /// Prepare data for generate support points /// Used for interactive resampling to store permanent data between configuration changes., /// Everything which could be prepared are stored into result. /// Need to regenerate on mesh change(Should be connected with ObjectId) OR change of slicing heights /// /// Countour cut from mesh /// Heights of the slices - Same size as slices /// Call in meanwhile to check cancel event /// Say progress of generation into gui /// Data prepared for generate support points SupportPointGeneratorData prepare_generator_data( std::vector &&slices, const std::vector &heights, ThrowOnCancel throw_on_cancel, StatusFunction statusfn ); /// /// Generate support points on islands by configuration parameters /// /// Preprocessed data needed for sampling /// Define density of samples /// Call in meanwhile to check cancel event /// Progress of generation into gui /// Generated support points LayerSupportPoints generate_support_points( const SupportPointGeneratorData &data, const SupportPointGeneratorConfig &config, ThrowOnCancel throw_on_cancel, StatusFunction statusfn ); } // namespace Slic3r::sla // TODO: Not sure if it is neccessary & Should be in another file namespace Slic3r{ class AABBMesh; namespace sla { /// /// Move support points on surface of mesh /// /// Support points to move on surface /// Define surface for move points /// Call in meanwhile to check cancel event /// Support points laying on mesh surface SupportPoints move_on_mesh_surface( const LayerSupportPoints &points, const AABBMesh &mesh, double allowed_move, ThrowOnCancel throw_on_cancel ); }} #endif // SLA_SUPPORTPOINTGENERATOR_HPP