Merge branch 'master' into fs_emboss

# Conflicts:
#	src/libslic3r/AABBTreeLines.hpp
#	src/libslic3r/ExPolygon.hpp
#	tests/libslic3r/test_aabbindirect.cpp
This commit is contained in:
Filip Sykala - NTB T15p 2022-10-05 15:14:54 +02:00
commit e340fa6abe
15 changed files with 1046 additions and 842 deletions

View file

@ -1,2 +1,3 @@
min_slic3r_version = 2.5.0-alpha3
1.0.0 Initial version
min_slic3r_version = 2.5.0-alpha3
1.0.1 Decreased bed size to 220x220.
1.0.0 Initial version

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,2 @@
min_slic3r_version = 2.6.0-alpha1
0.0.1 Initial version

View file

@ -0,0 +1,131 @@
# Print profiles for Print4Taste printers (mycusini and procusini brands)
# Created from scratch from default FFF
[vendor]
# Vendor name will be shown by the Config Wizard.
name = Print4Taste
# Configuration version of this file. Config file will only be installed, if the config_version differs.
# This means, the server may force the PrusaSlicer configuration to be downgraded.
config_version = 0.0.1
# Where to get the updates from?
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Print4Taste/
# The printer models will be shown by the Configuration Wizard in this order,
# also the first model installed & the first nozzle installed will be activated after install.
# Printer model name will be shown by the installation wizard.
[printer_model:MC2.0]
name = mycusini 2.0
variants = 1.0
technology = FFF
family = mycusini
bed_model = MC2.0_bed.stl
bed_texture = MC2.0_texture.svg
default_materials = mycusini 3D Choco @MC2.0
[print:*common_MC2.0*]
bottom_solid_layers = 2
bridge_speed = 30
brim_type = no_brim
compatible_printers_condition = printer_notes=~/.*PRINT4TASTE.*/ and printer_notes=~/.*MYCUSINI2.0.*/
elefant_foot_compensation = 0.1
ensure_vertical_shell_thickness = 1
external_perimeter_extrusion_width = 1.15
external_perimeter_speed = 100%
extra_perimeters = 0
extruder_clearance_height = 45
extruder_clearance_radius = 40
extrusion_width = 1.15
fill_density = 20%
fill_pattern = grid
first_layer_extrusion_width = 1.15
first_layer_height = 0.5
first_layer_speed = 100%
gap_fill_speed = 30
infill_anchor = 250%
infill_extrusion_width = 1
infill_overlap = 5%
infill_speed = 30
layer_height = 0.5
max_print_speed = 80
max_volumetric_extrusion_rate_slope_negative = 2
max_volumetric_extrusion_rate_slope_positive = 2
max_volumetric_speed = 8
notes = Extruder clearances:\nHeight: 45 Radius: 40\nHeight: 8 Radius: 12\n\nDon't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRINT4TASTE\nPRINTER_MODEL_MYCUSINI2.0
output_filename_format = [input_filename_base].gco
perimeter_extrusion_width = 1.15
perimeter_speed = 30
perimeters = 1
slice_closing_radius = 0.49
small_perimeter_speed = 100%
solid_infill_below_area = 10
solid_infill_extrusion_width = 1.15
solid_infill_speed = 100%
thin_walls = 0
top_infill_extrusion_width = 1.15
top_solid_infill_speed = 100%
top_solid_layers = 3
travel_speed = 80
skirts = 0
[print:0.50mm SOLID @MC2.0]
inherits = *common_MC2.0*
[print:0.50mm FILLABLE @MC2.0]
inherits = 0.50mm SOLID @MC2.0
top_solid_layers = 0
fill_density = 0%
spiral_vase = 1
[print:0.50mm OUTLINES @MC2.0]
inherits = 0.50mm FILLABLE @MC2.0
bottom_solid_layers = 0
[filament:mycusini 3D Choco @MC2.0]
filament_vendor = Print4Taste
bed_temperature = 0
bridge_fan_speed = 0
compatible_printers_condition = printer_notes=~/.*PRINT4TASTE.*/ and printer_notes=~/.*MYCUSINI2.0.*/
cooling = 1
disable_fan_first_layers = 0
end_filament_gcode = ""
extrusion_multiplier = 0.95
fan_always_on = 0
fan_below_layer_time = 60
filament_colour = #F4A6FF
filament_density = 1.26
filament_diameter = 18
filament_max_volumetric_speed = 8
filament_notes = "Full cartridge: 18 x 100 mm, 32g\nDensity: 1.26 g/cm3\nCut cartrige size: 18 x ~50 mm, 16g\nMycusini 2.0 does not require temperature control in gcode\n\n\nDon't remove the following keywords! These keywords are used in the \"compatible printer\" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRINT4TASTE\nPRINTER_MODEL_MYCUSINI2.0"
ilament_retract_before_wipe = 30%
filament_retract_layer_change = 1
filament_retract_length = 0.3
filament_retract_lift = 1
filament_type = GLAZE
filament_wipe = 1
first_layer_bed_temperature = 0
first_layer_temperature = 0
max_fan_speed = 0
min_fan_speed = 0
min_print_speed = 9
slowdown_below_layer_time = 15
start_filament_gcode = ""
temperature = 0
[printer:mycusini 2.0]
printer_model = MC2.0
printer_variant = 1.0
bed_shape = 5x2.5,105x2.5,105x112.5,5x112.5
color_change_gcode =
end_gcode = M83 ;Relative mode to retract\nG1 F2400 E-0.1 ;Retract\nM84 ;Back to absolute mode after retract\nG0 F2400 X90 Y55 Z45 ;Park
max_layer_height = 0.75
max_print_height = 45
min_layer_height = 0.3
nozzle_diameter = 1
pause_print_gcode =
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRINT4TASTE\nPRINTER_MODEL_MYCUSINI2.0
retract_length = 0.1
start_gcode = G1 F2400 E-0.3 ;Retract\nG0 F2400 X100 Y55 Z20.7 ;Full coordinates to prevent ramming down\nG0 F2400 X100 Y40 Z0.5 ;Start purge line\nG0 F570 X100 Y10 Z0.5 E0.025 ;Purge slightly more, should make a line only a few mm long
default_print_profile = 0.50mm SOLID @MC2.0
default_filament_profile = mycusini 3D Choco @MC2.0

Binary file not shown.

View file

@ -0,0 +1,165 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="100mm"
height="110mm"
viewBox="0 0 100 110"
version="1.1"
id="svg5"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
sodipodi:docname="mycusini2.0_printbed.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="true"
inkscape:document-units="mm"
showgrid="false"
inkscape:snap-to-guides="false"
inkscape:snap-grids="false"
inkscape:snap-global="true"
inkscape:zoom="8.7988368"
inkscape:cx="285.77641"
inkscape:cy="344.70465"
inkscape:window-width="3840"
inkscape:window-height="2080"
inkscape:window-x="-11"
inkscape:window-y="-11"
inkscape:window-maximized="1"
inkscape:current-layer="layer1"
inkscape:showpageshadow="2"
inkscape:deskcolor="#d1d1d1" />
<defs
id="defs2">
<marker
style="overflow:visible"
id="Arrow1Lstart"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Lstart"
inkscape:isstock="true">
<path
transform="scale(0.8) translate(12.5,0)"
style="fill-rule:evenodd;fill:context-stroke;stroke:context-stroke;stroke-width:1.0pt"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path2735" />
</marker>
</defs>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-17.350515,-57.494846)">
<rect
style="display:inline;fill:#ffffff;fill-opacity:0.5;stroke:none;stroke-width:2.83606;stroke-linejoin:round;stroke-dasharray:none"
id="rect6619"
width="100"
height="110"
x="17.350515"
y="57.494846" />
<path
id="rect1815"
style="display:inline;fill:#323232;fill-opacity:1;stroke:none;stroke-width:3.58768;stroke-linejoin:round;stroke-dasharray:none"
d="M 17.350515,57.494846 V 167.49485 H 117.35061 V 57.494846 Z m 4.88859,2.999817 h 90.222405 c 1.04636,0 1.88877,0.842404 1.88877,1.888773 V 162.60626 c 0,1.04637 -0.84241,1.88877 -1.88877,1.88877 H 22.239105 c -1.046369,0 -1.888773,-0.8424 -1.888773,-1.88877 V 62.383436 c 0,-1.046369 0.842404,-1.888773 1.888773,-1.888773 z" />
<rect
style="display:inline;fill:#323232;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.025227"
id="rect31"
width="100"
height="1"
x="17.350515"
y="-112.99484"
transform="scale(1,-1)" />
<rect
style="fill:#323232;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.0264583"
id="rect31-1"
width="1"
height="110"
x="66.850517"
y="-167.49484"
transform="scale(1,-1)" />
<rect
style="fill:#323232;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.0229831"
id="rect31-1-6"
width="1"
height="83"
x="91.850517"
y="-140.49481"
transform="scale(1,-1)" />
<rect
style="fill:#323232;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.0264583"
id="rect31-1-4"
width="1"
height="110"
x="41.850513"
y="-167.49484"
transform="scale(1,-1)" />
<rect
style="fill:#323232;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.025227"
id="rect31-5"
width="100"
height="1"
x="17.350515"
y="-140.49484"
transform="scale(1,-1)" />
<rect
style="fill:#323232;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.025227"
id="rect31-8"
width="100"
height="1"
x="17.350515"
y="-85.494843"
transform="scale(1,-1)" />
<g
transform="matrix(0.01004114,0,0,-0.01004115,77.288332,160.09414)"
fill="#000000"
stroke="none"
id="g1873"
style="fill:#323232;fill-opacity:1">
<path
d="m 1593,1049 c -25,-6 -58,-24 -78,-43 -21,-20 -50,-36 -71,-39 -83,-14 -127,-72 -121,-160 3,-46 9,-63 32,-87 16,-17 44,-35 61,-42 30,-11 33,-16 36,-57 3,-51 29,-68 53,-34 12,16 29,18 143,18 113,0 133,-2 151,-19 30,-28 53,-6 49,47 -3,37 -1,41 26,48 34,9 72,43 92,81 44,85 -22,203 -119,212 -23,2 -49,13 -65,28 -51,48 -115,64 -189,47 z m 128,-65 c 33,-17 57,-53 67,-101 6,-29 13,-39 31,-41 22,-3 23,-1 19,37 -2,29 0,41 10,41 25,0 61,-32 72,-65 21,-63 -22,-118 -100,-127 -21,-3 -25,-9 -28,-40 -3,-36 -3,-37 -40,-30 -48,9 -166,9 -214,0 -38,-7 -38,-7 -38,28 0,29 -3,34 -25,34 -58,0 -105,47 -105,104 0,29 41,81 69,89 18,4 20,0 18,-32 -2,-32 1,-36 23,-36 20,0 26,6 30,35 8,47 24,75 57,98 48,34 96,36 154,6 z"
id="path1855"
style="fill:#323232;fill-opacity:1" />
<path
d="M 107,536 C 24,506 9,474 7,317 5,197 5,195 28,192 c 12,-2 22,0 22,5 4,210 6,229 23,255 37,54 123,60 168,12 22,-23 24,-37 29,-147 4,-109 7,-122 24,-125 30,-6 36,16 36,134 0,110 0,110 31,140 42,40 106,41 146,1 27,-26 28,-32 33,-150 4,-109 7,-122 24,-125 29,-6 36,16 36,113 0,116 -11,155 -59,198 -63,57 -155,58 -216,1 l -27,-25 -27,26 c -26,24 -79,46 -111,45 -8,-1 -32,-7 -53,-14 z"
id="path1857"
style="fill:#323232;fill-opacity:1" />
<path
d="m 674,536 c -3,-8 -4,-67 -2,-130 3,-123 11,-145 70,-189 39,-29 114,-33 161,-9 l 37,20 V 173 C 940,124 936,114 906,84 865,43 809,37 766,71 737,94 707,90 712,64 718,30 766,7 828,7 c 64,0 104,18 137,61 18,25 20,45 23,246 2,120 -1,223 -6,228 -5,5 -16,6 -25,2 -15,-5 -17,-23 -17,-121 V 308 l -34,-34 c -27,-27 -42,-34 -73,-34 -83,0 -106,40 -113,190 -4,99 -7,115 -23,118 -9,2 -20,-3 -23,-12 z"
id="path1859"
style="fill:#323232;fill-opacity:1" />
<path
d="m 1177,535 c -76,-27 -117,-84 -117,-165 0,-102 59,-170 155,-178 30,-2 65,-2 79,2 35,9 86,54 86,77 0,24 -32,25 -51,2 -23,-26 -78,-45 -112,-37 -46,10 -73,31 -91,69 -32,66 -12,139 47,175 49,30 99,26 142,-11 57,-50 93,-16 38,36 -47,43 -110,54 -176,30 z"
id="path1861"
style="fill:#323232;fill-opacity:1" />
<path
d="m 1994,540 c -31,-12 -64,-59 -64,-90 0,-46 34,-78 110,-101 78,-23 95,-38 86,-73 -12,-47 -99,-53 -162,-11 -23,15 -28,15 -41,2 -49,-48 130,-102 207,-62 36,19 50,43 50,90 0,47 -31,75 -107,99 -88,28 -112,56 -75,89 23,21 72,22 119,2 31,-13 39,-13 51,-2 38,39 -104,85 -174,57 z"
id="path1863"
style="fill:#323232;fill-opacity:1" />
<path
d="m 2321,541 c -8,-5 -11,-55 -9,-177 3,-161 4,-169 23,-169 19,0 20,8 23,171 2,138 0,173 -11,177 -8,3 -19,2 -26,-2 z"
id="path1865"
style="fill:#323232;fill-opacity:1" />
<path
d="m 2590,528 c -77,-40 -85,-60 -85,-206 0,-120 1,-127 20,-127 19,0 20,8 25,115 3,66 10,125 18,137 15,26 61,53 92,53 31,0 77,-27 92,-53 8,-12 15,-71 18,-137 5,-107 6,-115 25,-115 19,0 20,8 23,121 2,111 1,123 -20,155 -25,37 -98,79 -138,79 -14,0 -46,-10 -70,-22 z"
id="path1867"
style="fill:#323232;fill-opacity:1" />
<path
d="m 1490,417 c 0,-112 2,-127 23,-157 64,-95 200,-93 271,3 19,25 21,42 21,150 0,119 -1,122 -22,125 -23,3 -23,1 -23,-98 0,-110 -13,-157 -51,-184 -46,-32 -134,-14 -155,32 -5,9 -11,69 -14,132 -5,110 -6,115 -27,118 -23,3 -23,2 -23,-121 z"
id="path1869"
style="fill:#323232;fill-opacity:1" />
<path
d="m 2952,368 c 3,-163 4,-173 22,-173 19,0 20,9 20,170 0,168 -1,170 -22,173 l -22,3 z"
id="path1871"
style="fill:#323232;fill-opacity:1" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View file

@ -519,7 +519,7 @@ namespace detail {
const VectorType origin;
inline VectorType closest_point_to_origin(size_t primitive_index,
ScalarType& squared_distance){
ScalarType& squared_distance) const {
const auto &triangle = this->faces[primitive_index];
VectorType closest_point = closest_point_to_triangle<VectorType>(origin,
this->vertices[triangle(0)].template cast<ScalarType>(),
@ -613,6 +613,37 @@ namespace detail {
return up_sqr_d;
}
template<typename IndexedPrimitivesDistancerType, typename Scalar>
static inline void indexed_primitives_within_distance_squared_recurisve(const IndexedPrimitivesDistancerType &distancer,
size_t node_idx,
Scalar squared_distance_limit,
std::vector<size_t> &found_primitives_indices)
{
const auto &node = distancer.tree.node(node_idx);
assert(node.is_valid());
if (node.is_leaf()) {
Scalar sqr_dist;
distancer.closest_point_to_origin(node.idx, sqr_dist);
if (sqr_dist < squared_distance_limit) { found_primitives_indices.push_back(node.idx); }
} else {
size_t left_node_idx = node_idx * 2 + 1;
size_t right_node_idx = left_node_idx + 1;
const auto &node_left = distancer.tree.node(left_node_idx);
const auto &node_right = distancer.tree.node(right_node_idx);
assert(node_left.is_valid());
assert(node_right.is_valid());
if (node_left.bbox.squaredExteriorDistance(distancer.origin) < squared_distance_limit) {
indexed_primitives_within_distance_squared_recurisve(distancer, left_node_idx, squared_distance_limit,
found_primitives_indices);
}
if (node_right.bbox.squaredExteriorDistance(distancer.origin) < squared_distance_limit) {
indexed_primitives_within_distance_squared_recurisve(distancer, right_node_idx, squared_distance_limit,
found_primitives_indices);
}
}
}
} // namespace detail
// Build a balanced AABB Tree over an indexed triangles set, balancing the tree
@ -799,6 +830,33 @@ inline bool is_any_triangle_in_radius(
return hit_point.allFinite();
}
// Returns all triangles within the given radius limit
template<typename VertexType, typename IndexedFaceType, typename TreeType, typename VectorType>
inline std::vector<size_t> all_triangles_in_radius(
// Indexed triangle set - 3D vertices.
const std::vector<VertexType> &vertices,
// Indexed triangle set - triangular faces, references to vertices.
const std::vector<IndexedFaceType> &faces,
// AABBTreeIndirect::Tree over vertices & faces, bounding boxes built with the accuracy of vertices.
const TreeType &tree,
// Point to which the distances on the indexed triangle set is searched for.
const VectorType &point,
//Square of maximum distance in which triangles are searched for
typename VectorType::Scalar max_distance_squared)
{
auto distancer = detail::IndexedTriangleSetDistancer<VertexType, IndexedFaceType, TreeType, VectorType>
{ vertices, faces, tree, point };
if(tree.empty())
{
return {};
}
std::vector<size_t> found_triangles{};
detail::indexed_primitives_within_distance_squared_recurisve(distancer, size_t(0), max_distance_squared, found_triangles);
return found_triangles;
}
// Traverse the tree and return the index of an entity whose bounding box
// contains a given point. Returns size_t(-1) when the point is outside.

View file

@ -1,8 +1,12 @@
#ifndef SRC_LIBSLIC3R_AABBTREELINES_HPP_
#define SRC_LIBSLIC3R_AABBTREELINES_HPP_
#include "Utils.hpp"
#include "libslic3r.h"
#include "libslic3r/AABBTreeIndirect.hpp"
#include "libslic3r/Line.hpp"
#include <type_traits>
#include <vector>
namespace Slic3r {
@ -23,17 +27,17 @@ struct IndexedLinesDistancer {
const VectorType origin;
inline VectorType closest_point_to_origin(size_t primitive_index,
ScalarType &squared_distance) {
VectorType nearest_point;
ScalarType &squared_distance) const {
Vec<LineType::Dim, typename LineType::Scalar> nearest_point;
const LineType &line = lines[primitive_index];
squared_distance = line_alg::distance_to_squared(line, origin, &nearest_point);
return nearest_point;
squared_distance = line_alg::distance_to_squared(line, origin.template cast<typename LineType::Scalar>(), &nearest_point);
return nearest_point.template cast<ScalarType>();
}
};
}
// Build a balanced AABB Tree over a vector of float lines, balancing the tree
// Build a balanced AABB Tree over a vector of lines, balancing the tree
// on centroids of the lines.
// Epsilon is applied to the bounding boxes of the AABB Tree to cope with numeric inaccuracies
// during tree traversal.
@ -41,7 +45,7 @@ template<typename LineType>
inline AABBTreeIndirect::Tree<2, typename LineType::Scalar> build_aabb_tree_over_indexed_lines(
const std::vector<LineType> &lines,
//FIXME do we want to apply an epsilon?
const float eps = 0)
const double eps = 0)
{
using TreeType = AABBTreeIndirect::Tree<2, typename LineType::Scalar>;
// using CoordType = typename TreeType::CoordType;
@ -85,29 +89,100 @@ inline AABBTreeIndirect::Tree<2, typename LineType::Scalar> build_aabb_tree_over
}
// Finding a closest line, its closest point and squared distance to the closest point
// Returns squared distance to the closest point or -1 if the input is empty
// Returns squared distance to the closest point or -1 if the input is empty.
// or no closer point than max_sq_dist
template<typename LineType, typename TreeType, typename VectorType,
typename Scalar = typename VectorType::Scalar>
inline typename VectorType::Scalar squared_distance_to_indexed_lines(
const std::vector<LineType> &lines,
const TreeType &tree,
const VectorType &point,
size_t &hit_idx_out,
Eigen::PlainObjectBase<VectorType> &hit_point_out,
Scalar max_sqr_dist = std::numeric_limits<Scalar>::infinity())
template<typename LineType, typename TreeType, typename VectorType, typename Scalar = typename VectorType::Scalar>
inline typename Scalar squared_distance_to_indexed_lines(const std::vector<LineType> &lines,
const TreeType &tree,
const VectorType &point,
size_t &hit_idx_out,
Eigen::PlainObjectBase<VectorType> &hit_point_out,
Scalar max_sqr_dist = std::numeric_limits<Scalar>::infinity())
{
if (tree.empty()) return Scalar(-1);
auto distancer = detail::IndexedLinesDistancer<LineType, TreeType, VectorType>
{ lines, tree, point };
hit_idx_out = std::numeric_limits<size_t>::max();
Scalar distance = AABBTreeIndirect::detail::squared_distance_to_indexed_primitives_recursive(
auto distancer = detail::IndexedLinesDistancer<LineType, TreeType, VectorType>{lines, tree, point};
return AABBTreeIndirect::detail::squared_distance_to_indexed_primitives_recursive(
distancer, size_t(0), Scalar(0), max_sqr_dist, hit_idx_out, hit_point_out);
if (hit_idx_out == std::numeric_limits<size_t>::max()) return Scalar(-1);
return distance;
}
// Returns all lines within the given radius limit
template<typename LineType, typename TreeType, typename VectorType>
inline std::vector<size_t> all_lines_in_radius(const std::vector<LineType> &lines,
const TreeType &tree,
const VectorType &point,
typename VectorType::Scalar max_distance_squared)
{
auto distancer = detail::IndexedLinesDistancer<LineType, TreeType, VectorType>{lines, tree, point};
if (tree.empty()) { return {}; }
std::vector<size_t> found_lines{};
AABBTreeIndirect::detail::indexed_primitives_within_distance_squared_recurisve(distancer, size_t(0), max_distance_squared, found_lines);
return found_lines;
}
}
template<typename LineType> class LinesDistancer
{
private:
std::vector<LineType> lines;
using Scalar = typename LineType::Scalar;
using Floating = typename std::conditional<std::is_floating_point<Scalar>::value, Scalar, double>::type;
AABBTreeIndirect::Tree<2, Scalar> tree;
public:
explicit LinesDistancer(const std::vector<LineType> &lines) : lines(lines)
{
tree = AABBTreeLines::build_aabb_tree_over_indexed_lines(this->lines);
}
// negative sign means inside
std::tuple<Floating, size_t, Vec<2, Floating>> signed_distance_from_lines_extra(const Vec<2, Scalar> &point) const
{
size_t nearest_line_index_out = size_t(-1);
Vec<2, Floating> nearest_point_out = Vec<2, Floating>::Zero();
Vec<2, Floating> p = point.template cast<Floating>();
auto distance = AABBTreeLines::squared_distance_to_indexed_lines(lines, tree, p, nearest_line_index_out, nearest_point_out);
if (distance < 0) { return {std::numeric_limits<Floating>::infinity(), nearest_line_index_out, nearest_point_out}; }
distance = sqrt(distance);
const LineType &line = lines[nearest_line_index_out];
Vec<2, Floating> v1 = (line.b - line.a).template cast<Floating>();
Vec<2, Floating> v2 = (point - line.a).template cast<Floating>();
auto d1 = (v1.x() * v2.y()) - (v1.y() * v2.x());
LineType second_line = line;
if ((line.a.template cast<Floating>() - nearest_point_out).squaredNorm() < SCALED_EPSILON) {
second_line = lines[prev_idx_modulo(nearest_line_index_out, lines.size())];
} else {
second_line = lines[next_idx_modulo(nearest_line_index_out, lines.size())];
}
v1 = (second_line.b - second_line.a).template cast<Floating>();
v2 = (point - second_line.a).template cast<Floating>();
auto d2 = (v1.x() * v2.y()) - (v1.y() * v2.x());
auto d = abs(d1) > abs(d2) ? d1 : d2;
if (d > 0.0) { distance *= -1.0; }
return {distance, nearest_line_index_out, nearest_point_out};
}
Floating signed_distance_from_lines(const Vec<2, typename LineType::Scalar> &point) const
{
auto [dist, idx, np] = signed_distance_from_lines_extra(point);
return dist;
}
std::vector<size_t> all_lines_in_radius(const Vec<2, typename LineType::Scalar> &point, Floating radius)
{
return all_lines_in_radius(this->lines, this->tree, point, radius * radius);
}
const LineType &get_line(size_t line_idx) const { return lines[line_idx]; }
const std::vector<LineType> &get_lines() const { return lines; }
};
}} // namespace Slic3r::AABBTreeLines
#endif /* SRC_LIBSLIC3R_AABBTREELINES_HPP_ */

View file

@ -19,6 +19,7 @@ set(SLIC3R_SOURCES
pchheader.hpp
AStar.hpp
AABBTreeIndirect.hpp
AABBTreeLines.hpp
AABBMesh.hpp
AABBMesh.cpp
BoundingBox.cpp
@ -274,7 +275,6 @@ set(SLIC3R_SOURCES
TriangleMeshSlicer.hpp
MeshSplitImpl.hpp
TriangulateWall.hpp
TriangulateWall.cpp
utils.cpp
Utils.hpp
Time.cpp

View file

@ -1,6 +1,7 @@
#ifndef slic3r_ExPolygon_hpp_
#define slic3r_ExPolygon_hpp_
#include "Point.hpp"
#include "libslic3r.h"
#include "Polygon.hpp"
#include "Polyline.hpp"
@ -134,6 +135,28 @@ inline Lines to_lines(const ExPolygons &src)
return lines;
}
inline std::vector<Linef> to_linesf(const ExPolygons &src)
{
size_t n_lines = 0;
for (ExPolygons::const_iterator it_expoly = src.begin(); it_expoly != src.end(); ++ it_expoly) {
n_lines += it_expoly->contour.points.size();
for (size_t i = 0; i < it_expoly->holes.size(); ++ i)
n_lines += it_expoly->holes[i].points.size();
}
std::vector<Linef> lines;
lines.reserve(n_lines);
for (ExPolygons::const_iterator it_expoly = src.begin(); it_expoly != src.end(); ++ it_expoly) {
for (size_t i = 0; i <= it_expoly->holes.size(); ++ i) {
const Points &points = ((i == 0) ? it_expoly->contour : it_expoly->holes[i - 1]).points;
for (Points::const_iterator it = points.begin(); it != points.end()-1; ++it)
lines.push_back(Linef(unscaled(*it), unscaled(*(it + 1))));
lines.push_back(Linef(unscaled(points.back()), unscaled(points.front())));
}
}
return lines;
}
inline Points to_points(const ExPolygons &src)
{
Points points;

View file

@ -1,6 +1,7 @@
#include "SeamPlacer.hpp"
#include "Color.hpp"
#include "Polygon.hpp"
#include "PrintConfig.hpp"
#include "tbb/parallel_for.h"
#include "tbb/blocked_range.h"
@ -995,49 +996,6 @@ void pick_random_seam_point(const std::vector<SeamCandidate> &perimeter_points,
perimeter.finalized = true;
}
class PerimeterDistancer {
std::vector<Linef> lines;
AABBTreeIndirect::Tree<2, double> tree;
public:
PerimeterDistancer(const Layer *layer) {
ExPolygons layer_outline = layer->lslices;
for (const ExPolygon &island : layer_outline) {
assert(island.contour.is_counter_clockwise());
for (const auto &line : island.contour.lines()) {
lines.emplace_back(unscale(line.a), unscale(line.b));
}
for (const Polygon &hole : island.holes) {
assert(hole.is_clockwise());
for (const auto &line : hole.lines()) {
lines.emplace_back(unscale(line.a), unscale(line.b));
}
}
}
tree = AABBTreeLines::build_aabb_tree_over_indexed_lines(lines);
}
float distance_from_perimeter(const Vec2f &point) const {
Vec2d p = point.cast<double>();
size_t hit_idx_out { };
Vec2d hit_point_out = Vec2d::Zero();
auto distance = AABBTreeLines::squared_distance_to_indexed_lines(lines, tree, p, hit_idx_out, hit_point_out);
if (distance < 0) {
return std::numeric_limits<float>::max();
}
distance = sqrt(distance);
const Linef &line = lines[hit_idx_out];
Vec2d v1 = line.b - line.a;
Vec2d v2 = p - line.a;
if ((v1.x() * v2.y()) - (v1.y() * v2.x()) > 0.0) {
distance *= -1;
}
return distance;
}
}
;
} // namespace SeamPlacerImpl
// Parallel process and extract each perimeter polygon of the given print object.
@ -1089,13 +1047,14 @@ void SeamPlacer::calculate_candidates_visibility(const PrintObject *po,
void SeamPlacer::calculate_overhangs_and_layer_embedding(const PrintObject *po) {
using namespace SeamPlacerImpl;
using PerimeterDistancer = AABBTreeLines::LinesDistancer<Linef>;
std::vector<PrintObjectSeamData::LayerSeams> &layers = m_seam_per_object[po].layers;
tbb::parallel_for(tbb::blocked_range<size_t>(0, layers.size()),
[po, &layers](tbb::blocked_range<size_t> r) {
std::unique_ptr<PerimeterDistancer> prev_layer_distancer;
if (r.begin() > 0) { // previous layer exists
prev_layer_distancer = std::make_unique<PerimeterDistancer>(po->layers()[r.begin() - 1]);
prev_layer_distancer = std::make_unique<PerimeterDistancer>(to_linesf(po->layers()[r.begin() - 1]->lslices));
}
for (size_t layer_idx = r.begin(); layer_idx < r.end(); ++layer_idx) {
@ -1106,12 +1065,12 @@ void SeamPlacer::calculate_overhangs_and_layer_embedding(const PrintObject *po)
}
};
bool should_compute_layer_embedding = regions_with_perimeter > 1;
std::unique_ptr<PerimeterDistancer> current_layer_distancer = std::make_unique<PerimeterDistancer>(po->layers()[layer_idx]);
std::unique_ptr<PerimeterDistancer> current_layer_distancer = std::make_unique<PerimeterDistancer>(to_linesf(po->layers()[layer_idx]->lslices));
for (SeamCandidate &perimeter_point : layers[layer_idx].points) {
Vec2f point = Vec2f { perimeter_point.position.head<2>() };
if (prev_layer_distancer.get() != nullptr) {
perimeter_point.overhang = prev_layer_distancer->distance_from_perimeter(point)
perimeter_point.overhang = prev_layer_distancer->signed_distance_from_lines(point.cast<double>())
+ 0.6f * perimeter_point.perimeter.flow_width
- tan(SeamPlacer::overhang_angle_threshold)
* po->layers()[layer_idx]->height;
@ -1120,7 +1079,7 @@ void SeamPlacer::calculate_overhangs_and_layer_embedding(const PrintObject *po)
}
if (should_compute_layer_embedding) { // search for embedded perimeter points (points hidden inside the print ,e.g. multimaterial join, best position for seam)
perimeter_point.embedded_distance = current_layer_distancer->distance_from_perimeter(point)
perimeter_point.embedded_distance = current_layer_distancer->signed_distance_from_lines(point.cast<double>())
+ 0.6f * perimeter_point.perimeter.flow_width;
}
}

View file

@ -1,6 +1,9 @@
#include "SupportSpotsGenerator.hpp"
#include "ExPolygon.hpp"
#include "ExtrusionEntity.hpp"
#include "Line.hpp"
#include "Polygon.hpp"
#include "tbb/parallel_for.h"
#include "tbb/blocked_range.h"
#include "tbb/blocked_range2d.h"
@ -70,46 +73,10 @@ SupportPoint::SupportPoint(const Vec3f &position, float force, float spot_radius
position(position), force(force), spot_radius(spot_radius), direction(direction) {
}
class LinesDistancer {
private:
std::vector<ExtrusionLine> lines;
AABBTreeIndirect::Tree<2, float> tree;
public:
explicit LinesDistancer(const std::vector<ExtrusionLine> &lines) :
lines(lines) {
tree = AABBTreeLines::build_aabb_tree_over_indexed_lines(this->lines);
}
// negative sign means inside
float signed_distance_from_lines(const Vec2f &point, size_t &nearest_line_index_out,
Vec2f &nearest_point_out) const {
auto distance = AABBTreeLines::squared_distance_to_indexed_lines(lines, tree, point, nearest_line_index_out,
nearest_point_out);
if (distance < 0)
return std::numeric_limits<float>::infinity();
distance = sqrt(distance);
const ExtrusionLine &line = lines[nearest_line_index_out];
Vec2f v1 = line.b - line.a;
Vec2f v2 = point - line.a;
if ((v1.x() * v2.y()) - (v1.y() * v2.x()) > 0.0) {
distance *= -1;
}
return distance;
}
const ExtrusionLine& get_line(size_t line_idx) const {
return lines[line_idx];
}
const std::vector<ExtrusionLine>& get_lines() const {
return lines;
}
};
static const size_t NULL_ISLAND = std::numeric_limits<size_t>::max();
using LD = AABBTreeLines::LinesDistancer<ExtrusionLine>;
class PixelGrid {
Vec2f pixel_size;
Vec2f origin;
@ -387,7 +354,7 @@ void check_extrusion_entity_stability(const ExtrusionEntity *entity,
std::vector<ExtrusionLine> &checked_lines_out,
float layer_z,
const LayerRegion *layer_region,
const LinesDistancer &prev_layer_lines,
const LD &prev_layer_lines,
Issues &issues,
const Params &params) {
@ -429,11 +396,7 @@ void check_extrusion_entity_stability(const ExtrusionEntity *entity,
// malformation in concave angles does not happen
malformation_acc.add_angle(std::max(0.0f, curr_angle));
size_t nearest_line_idx;
Vec2f nearest_point;
float dist_from_prev_layer = prev_layer_lines.signed_distance_from_lines(current_line.b, nearest_line_idx,
nearest_point);
auto [dist_from_prev_layer, nearest_line_idx, nearest_point] = prev_layer_lines.signed_distance_from_lines_extra(current_line.b);
if (fabs(dist_from_prev_layer) < overhang_dist) {
bridging_acc.reset();
} else {
@ -491,53 +454,18 @@ std::tuple<LayerIslands, PixelGrid> reckon_islands(
}
}
std::vector<LinesDistancer> islands; // these search trees will be used to determine to which island does the extrusion belong.
std::vector<std::vector<size_t>> island_extrusions; //final assigment of each extrusion to an island.
// initliaze the search from external perimeters - at the beginning, there is island candidate for each external perimeter.
// some of them will disappear (e.g. holes)
for (size_t e = 0; e < extrusions.size(); ++e) {
if (layer_lines[extrusions[e].first].origin_entity->is_loop() &&
layer_lines[extrusions[e].first].is_external_perimeter()) {
std::vector<ExtrusionLine> copy(extrusions[e].second - extrusions[e].first);
for (size_t ex_line_idx = extrusions[e].first; ex_line_idx < extrusions[e].second; ++ex_line_idx) {
copy[ex_line_idx - extrusions[e].first] = layer_lines[ex_line_idx];
}
islands.emplace_back(copy);
island_extrusions.push_back( { e });
}
std::vector<AABBTreeLines::LinesDistancer<Line>> islands; // these search trees will be used to determine to which island does the extrusion belong.
for (const ExPolygon& island : layer->lslices) {
islands.emplace_back(to_lines(island));
}
// backup code if islands not found
// If that happens, just make the first extrusion into island - it may be wrong, but it won't crash.
if (islands.empty() && !extrusions.empty()) {
std::vector<ExtrusionLine> copy(extrusions[0].second - extrusions[0].first);
for (size_t ex_line_idx = extrusions[0].first; ex_line_idx < extrusions[0].second; ++ex_line_idx) {
copy[ex_line_idx - extrusions[0].first] = layer_lines[ex_line_idx];
}
islands.emplace_back(copy);
island_extrusions.push_back( { 0 });
}
// assign non external extrusions to islands
for (size_t e = 0; e < extrusions.size(); ++e) {
if (!layer_lines[extrusions[e].first].origin_entity->is_loop() ||
!layer_lines[extrusions[e].first].is_external_perimeter()) {
bool island_assigned = false;
for (size_t i = 0; i < islands.size(); ++i) {
if (island_extrusions[i].empty()) {
continue;
}
size_t idx = 0;
Vec2f pt = Vec2f::Zero();
if (islands[i].signed_distance_from_lines(layer_lines[extrusions[e].first].a, idx, pt) < 0) {
island_extrusions[i].push_back(e);
island_assigned = true;
break;
}
}
if (!island_assigned) { // If extrusion is not assigned for some reason, push it into the first island. As with the previous backup code,
// it may be wrong, but it won't crash
island_extrusions[0].push_back(e);
std::vector<std::vector<size_t>> island_extrusions(islands.size(),
std::vector<size_t>{}); // final assigment of each extrusion to an island.
for (size_t extrusion_idx = 0; extrusion_idx < extrusions.size(); extrusion_idx++) {
Point second_point = Point::new_scale(layer_lines[extrusions[extrusion_idx].first].b);
for (size_t island_idx = 0; island_idx < islands.size(); island_idx++) {
if (islands[island_idx].signed_distance_from_lines(second_point) <= 0.0) {
island_extrusions[island_idx].push_back(extrusion_idx);
}
}
}
@ -553,10 +481,14 @@ std::tuple<LayerIslands, PixelGrid> reckon_islands(
}
Island island { };
island.external_lines.insert(island.external_lines.end(),
layer_lines.begin() + extrusions[island_ex[0]].first,
layer_lines.begin() + extrusions[island_ex[0]].second);
for (size_t extrusion_idx : island_ex) {
if (layer_lines[extrusions[extrusion_idx].first].is_external_perimeter()) {
island.external_lines.insert(island.external_lines.end(),
layer_lines.begin() + extrusions[extrusion_idx].first,
layer_lines.begin() + extrusions[extrusion_idx].second);
}
for (size_t lidx = extrusions[extrusion_idx].first; lidx < extrusions[extrusion_idx].second; ++lidx) {
line_to_island_mapping[lidx] = result.islands.size();
const ExtrusionLine &line = layer_lines[lidx];
@ -1050,7 +982,7 @@ Issues check_global_stability(SupportGridFilter supports_presence_grid,
#ifdef DETAILED_DEBUG_LOGS
weakest_conn.print_info("weakest connection info: ");
#endif
LinesDistancer island_lines_dist(island.external_lines);
LD island_lines_dist(island.external_lines);
float unchecked_dist = params.min_distance_between_support_points + 1.0f;
for (const ExtrusionLine &line : island.external_lines) {
@ -1059,12 +991,9 @@ Issues check_global_stability(SupportGridFilter supports_presence_grid,
unchecked_dist += line.len;
} else {
unchecked_dist = line.len;
Vec2f target_point;
size_t idx;
Vec3f pivot_site_search_point = to_3d(Vec2f(line.b + (line.b - line.a).normalized() * 300.0f),
layer_z);
island_lines_dist.signed_distance_from_lines(pivot_site_search_point.head<2>(), idx,
target_point);
auto [dist, nidx, target_point] = island_lines_dist.signed_distance_from_lines_extra(pivot_site_search_point.head<2>());
Vec3f support_point = to_3d(target_point, layer_z);
auto force = part.is_stable_while_extruding(weakest_conn, line, support_point, layer_z, params);
if (force > 0) {
@ -1147,7 +1076,7 @@ std::tuple<Issues, std::vector<LayerIslands>> check_extrusions_and_build_graph(c
}
}
#endif
LinesDistancer external_lines(layer_lines);
LD external_lines(layer_lines);
layer_lines.clear();
prev_layer_grid = layer_grid;
@ -1199,7 +1128,7 @@ std::tuple<Issues, std::vector<LayerIslands>> check_extrusions_and_build_graph(c
}
}
#endif
external_lines = LinesDistancer(layer_lines);
external_lines = LD(layer_lines);
layer_lines.clear();
prev_layer_grid = layer_grid;
}

View file

@ -1,159 +0,0 @@
#include "TriangulateWall.hpp"
#include "MTUtils.hpp"
namespace Slic3r {
//class Ring {
// size_t idx = 0, nextidx = 1, startidx = 0, begin = 0, end = 0;
//public:
// explicit Ring(size_t from, size_t to) : begin(from), end(to) { init(begin); }
// size_t size() const { return end - begin; }
// std::pair<size_t, size_t> pos() const { return {idx, nextidx}; }
// bool is_lower() const { return idx < size(); }
// void inc()
// {
// if (nextidx != startidx) nextidx++;
// if (nextidx == end) nextidx = begin;
// idx ++;
// if (idx == end) idx = begin;
// }
// void init(size_t pos)
// {
// startidx = begin + (pos - begin) % size();
// idx = startidx;
// nextidx = begin + (idx + 1 - begin) % size();
// }
// bool is_finished() const { return nextidx == idx; }
//};
//template<class Sc>
//static Sc sq_dst(const Vec<3, Sc> &v1, const Vec<3, Sc>& v2)
//{
// Vec<3, Sc> v = v1 - v2;
// return v.x() * v.x() + v.y() * v.y() /*+ v.z() * v.z()*/;
//}
//template<class Sc>
//static Sc trscore(const Ring & onring,
// const Ring & offring,
// const std::vector<Vec<3, Sc>> &pts)
//{
// Sc a = sq_dst(pts[onring.pos().first], pts[offring.pos().first]);
// Sc b = sq_dst(pts[onring.pos().second], pts[offring.pos().first]);
// return (std::abs(a) + std::abs(b)) / 2.;
//}
//template<class Sc>
//class Triangulator {
// const std::vector<Vec<3, Sc>> *pts;
// Ring *onring, *offring;
// double calc_score() const
// {
// return trscore(*onring, *offring, *pts);
// }
// void synchronize_rings()
// {
// Ring lring = *offring;
// auto minsc = trscore(*onring, lring, *pts);
// size_t imin = lring.pos().first;
// lring.inc();
// while(!lring.is_finished()) {
// double score = trscore(*onring, lring, *pts);
// if (score < minsc) { minsc = score; imin = lring.pos().first; }
// lring.inc();
// }
// offring->init(imin);
// }
// void emplace_indices(std::vector<Vec3i> &indices)
// {
// Vec3i tr{int(onring->pos().first), int(onring->pos().second),
// int(offring->pos().first)};
// if (onring->is_lower()) std::swap(tr(0), tr(1));
// indices.emplace_back(tr);
// }
//public:
// void run(std::vector<Vec3i> &indices)
// {
// synchronize_rings();
// double score = 0, prev_score = 0;
// while (!onring->is_finished() || !offring->is_finished()) {
// prev_score = score;
// if (onring->is_finished() || (score = calc_score()) > prev_score) {
// std::swap(onring, offring);
// } else {
// emplace_indices(indices);
// onring->inc();
// }
// }
// }
// explicit Triangulator(const std::vector<Vec<3, Sc>> *points,
// Ring & lower,
// Ring & upper)
// : pts{points}, onring{&upper}, offring{&lower}
// {}
//};
//template<class Sc, class I>
//void triangulate_wall(std::vector<Vec<3, Sc>> &pts,
// std::vector<Vec<3, I>> & ind,
// const Polygon & lower,
// const Polygon & upper,
// double lower_z_mm,
// double upper_z_mm)
//{
// if (upper.points.size() < 3 || lower.points.size() < 3) return;
// pts.reserve(lower.points.size() + upper.points.size());
// for (auto &p : lower.points)
// pts.emplace_back(unscaled(p.x()), unscaled(p.y()), lower_z_mm);
// for (auto &p : upper.points)
// pts.emplace_back(unscaled(p.x()), unscaled(p.y()), upper_z_mm);
// ind.reserve(2 * (lower.size() + upper.size()));
// Ring lring{0, lower.points.size()}, uring{lower.points.size(), pts.size()};
// Triangulator t{&pts, lring, uring};
// t.run(ind);
//}
//Wall triangulate_wall(const Polygon &lower,
// const Polygon &upper,
// double lower_z_mm,
// double upper_z_mm)
//{
// if (upper.points.size() < 3 || lower.points.size() < 3) return {};
// Wall wall;
// auto &pts = wall.first;
// auto &ind = wall.second;
// pts.reserve(lower.points.size() + upper.points.size());
// for (auto &p : lower.points)
// wall.first.emplace_back(unscaled(p.x()), unscaled(p.y()), lower_z_mm);
// for (auto &p : upper.points)
// wall.first.emplace_back(unscaled(p.x()), unscaled(p.y()), upper_z_mm);
// ind.reserve(2 * (lower.size() + upper.size()));
// Ring lring{0, lower.points.size()}, uring{lower.points.size(), pts.size()};
// Triangulator t{&pts, lring, uring};
// t.run(ind);
// return wall;
//}
} // namespace Slic3r

View file

@ -1,3 +1,4 @@
#include <algorithm>
#include <catch2/catch.hpp>
#include <test_utils.hpp>
@ -87,6 +88,25 @@ TEST_CASE("Creating a several 2d lines, testing closest point query", "[AABBIndi
REQUIRE(hit_point_out.y() == Approx(0.5));
}
TEST_CASE("Creating a several 2d lines, testing all lines in radius query", "[AABBIndirect]")
{
std::vector<Linef> lines { };
lines.push_back(Linef(Vec2d(0.0, 0.0), Vec2d(10.0, 0.0)));
lines.push_back(Linef(Vec2d(-10.0, 10.0), Vec2d(10.0, -10.0)));
lines.push_back(Linef(Vec2d(-2.0, -1.0), Vec2d(-2.0, 1.0)));
lines.push_back(Linef(Vec2d(-1.0, -1.0), Vec2d(-1.0, -1.0)));
lines.push_back(Linef(Vec2d(1.0, 1.0), Vec2d(1.0, 1.0)));
auto tree = AABBTreeLines::build_aabb_tree_over_indexed_lines(lines);
auto indices = AABBTreeLines::all_lines_in_radius(lines, tree, Vec2d{1.0,1.0}, 4.0);
REQUIRE(std::find(indices.begin(),indices.end(), 0) != indices.end());
REQUIRE(std::find(indices.begin(),indices.end(), 1) != indices.end());
REQUIRE(std::find(indices.begin(),indices.end(), 4) != indices.end());
REQUIRE(indices.size() == 3);
}
TEST_CASE("Find the closest point from ExPolys", "[ClosestPoint]") {
//////////////////////////////
// 0 - 3