mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-07-31 13:31:58 +08:00
Add uniform sampling of ExPolygon
This commit is contained in:
parent
f44b0d51f1
commit
b6ee9f4368
@ -26,6 +26,94 @@
|
||||
|
||||
using namespace Slic3r::sla;
|
||||
|
||||
std::vector<Slic3r::Vec2f> SampleIslandUtils::sample_expolygon(
|
||||
const ExPolygon &expoly, float samples_per_mm2)
|
||||
{
|
||||
const Points &points = expoly.contour.points;
|
||||
assert(!points.empty());
|
||||
// get y range
|
||||
coord_t min_y = points.front().y();
|
||||
coord_t max_y = min_y;
|
||||
for (const Point &point : points) {
|
||||
if (min_y > point.y())
|
||||
min_y = point.y();
|
||||
else if (max_y < point.y())
|
||||
max_y = point.y();
|
||||
}
|
||||
|
||||
static const float mm2_area = scale_(1) * scale_(1);
|
||||
// Equilateral triangle area = (side * height) / 2
|
||||
float triangle_area = mm2_area / samples_per_mm2;
|
||||
// Triangle area = sqrt(3) / 4 * "triangle side"
|
||||
static const float coef1 = sqrt(3.) / 4.;
|
||||
coord_t triangle_side = static_cast<coord_t>(
|
||||
std::round(sqrt(triangle_area * coef1)));
|
||||
coord_t triangle_side_2 = triangle_side / 2;
|
||||
static const float coef2 = sqrt(3.) / 2.;
|
||||
coord_t triangle_height = static_cast<coord_t>(
|
||||
std::round(triangle_side * coef2));
|
||||
|
||||
// IMPROVE: use line end y
|
||||
Lines lines = to_lines(expoly);
|
||||
// remove lines with y direction
|
||||
lines.erase(std::remove_if(lines.begin(), lines.end(),
|
||||
[](const Line &l) {
|
||||
return l.a.y() == l.b.y();
|
||||
}),
|
||||
lines.end());
|
||||
// change line direction from top to bottom
|
||||
for (Line &line : lines)
|
||||
if (line.a.y() > line.b.y()) std::swap(line.a, line.b);
|
||||
// sort by a.y()
|
||||
std::sort(lines.begin(), lines.end(),
|
||||
[](const Line &l1, const Line &l2) -> bool {
|
||||
return l1.a.y() < l2.a.y();
|
||||
});
|
||||
|
||||
std::vector<Vec2f> out;
|
||||
// size_t count_sample_lines = (max_y - min_y) / triangle_height;
|
||||
// out.reserve(count_sample_lines * count_sample_lines);
|
||||
|
||||
bool is_odd = false;
|
||||
for (coord_t y = min_y + triangle_height / 2; y < max_y;
|
||||
y += triangle_height) {
|
||||
is_odd = !is_odd;
|
||||
std::vector<coord_t> intersections;
|
||||
|
||||
for (auto line = std::begin(lines); line != std::end(lines); ++line) {
|
||||
const Point &b = line->b;
|
||||
if (b.y() <= y) {
|
||||
// line = lines.erase(line);
|
||||
continue;
|
||||
}
|
||||
const Point &a = line->a;
|
||||
if (a.y() >= y) break;
|
||||
float y_range = static_cast<float>(b.y() - a.y());
|
||||
float x_range = static_cast<float>(b.x() - a.x());
|
||||
float ratio = (y - a.y()) / y_range;
|
||||
coord_t intersection = a.x() +
|
||||
static_cast<coord_t>(x_range * ratio);
|
||||
intersections.push_back(intersection);
|
||||
}
|
||||
assert(intersections.size() % 2 == 0);
|
||||
std::sort(intersections.begin(), intersections.end());
|
||||
for (size_t index = 0; index + 1 < intersections.size(); index += 2) {
|
||||
coord_t start_x = intersections[index];
|
||||
coord_t end_x = intersections[index + 1];
|
||||
if (is_odd) start_x += triangle_side_2;
|
||||
coord_t div = start_x / triangle_side;
|
||||
if (start_x > 0) div += 1;
|
||||
coord_t x = div * triangle_side;
|
||||
if (is_odd) x -= triangle_side_2;
|
||||
while (x < end_x) {
|
||||
out.push_back(unscale(x, y).cast<float>());
|
||||
x += triangle_side;
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::unique_ptr<SupportIslandPoint> SampleIslandUtils::create_point(
|
||||
const VoronoiGraph::Node::Neighbor *neighbor,
|
||||
double ratio,
|
||||
|
@ -24,6 +24,14 @@ class SampleIslandUtils
|
||||
public:
|
||||
SampleIslandUtils() = delete;
|
||||
|
||||
/// <summary>
|
||||
/// Uniform sample expolygon area by points inside Equilateral triangle center
|
||||
/// </summary>
|
||||
/// <param name="expoly">Input area to sample. (scaled)</param>
|
||||
/// <param name="samples_per_mm2">Density of sampling.</param>
|
||||
/// <returns>Samples - 2d unscaled coordinates [in mm]</returns>
|
||||
static std::vector<Vec2f> sample_expolygon(const ExPolygon &expoly, float samples_per_mm2);
|
||||
|
||||
/// <summary>
|
||||
/// Create support point on edge defined by neighbor
|
||||
/// </summary>
|
||||
|
@ -158,10 +158,10 @@ Slic3r::Polygon create_cross_roads(double size, double width)
|
||||
|
||||
ExPolygon create_trinagle_with_hole(double size)
|
||||
{
|
||||
return ExPolygon(PolygonUtils::create_equilateral_triangle(size),
|
||||
{{size / 4, size / 4},
|
||||
{size / 2, size / 2},
|
||||
{size / 2, size / 4}});
|
||||
auto hole = PolygonUtils::create_equilateral_triangle(size / 3);
|
||||
hole.reverse();
|
||||
hole.rotate(3.14 / 4);
|
||||
return ExPolygon(PolygonUtils::create_equilateral_triangle(size), hole);
|
||||
}
|
||||
|
||||
ExPolygon create_square_with_hole(double size, double hole_size)
|
||||
@ -496,6 +496,54 @@ TEST_CASE("Speed align", "[VoronoiSkeleton]")
|
||||
}
|
||||
}
|
||||
|
||||
//#include <libslic3r/SLA/SupportPointGenerator.hpp>
|
||||
#include <libslic3r/SLA/SupportIslands/LineUtils.hpp>
|
||||
TEST_CASE("speed sampling", "[SupGen]") {
|
||||
double size = 3e7;
|
||||
float samples_per_mm2 = 0.01f;
|
||||
ExPolygons islands = createTestIslands(size);
|
||||
std::random_device rd;
|
||||
std::mt19937 m_rng;
|
||||
m_rng.seed(rd());
|
||||
|
||||
size_t count = 1;
|
||||
|
||||
std::vector<std::vector<Vec2f>> result1;
|
||||
result1.reserve(islands.size()*count);
|
||||
for (size_t i = 0; i<count; ++i)
|
||||
for (const auto& island: islands)
|
||||
result1.emplace_back(sample_expolygon(island, samples_per_mm2, m_rng));
|
||||
|
||||
std::vector<std::vector<Vec2f>> result2;
|
||||
result2.reserve(islands.size()*count);
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
for (const auto &island : islands)
|
||||
result2.emplace_back(SampleIslandUtils::sample_expolygon(island, samples_per_mm2)); //*/
|
||||
|
||||
/*size_t all = 0;
|
||||
for (auto& result : result2) {
|
||||
//std::cout << "case " << &result - &result1[0] << " points " << result.size() << std::endl;
|
||||
all += result.size();
|
||||
}
|
||||
std::cout << "All points " << all << std::endl;*/
|
||||
|
||||
for (size_t i = 0; i < result1.size(); ++i) {
|
||||
size_t island_index = i % islands.size();
|
||||
ExPolygon &island = islands[island_index];
|
||||
|
||||
Lines lines = to_lines(island.contour);
|
||||
std::string name = "sample_" + std::to_string(i) + ".svg";
|
||||
SVG svg(name, LineUtils::create_bounding_box(lines));
|
||||
svg.draw(island, "lightgray");
|
||||
svg.draw_text({0, 0}, ("random samples " + std::to_string(result1[i].size())).c_str(), "blue");
|
||||
for (Vec2f &p : result1[i])
|
||||
svg.draw((p * 1e6).cast<coord_t>(), "blue", 1e6);
|
||||
svg.draw_text({0., 5e6}, ("uniform samples " + std::to_string(result2[i].size())).c_str(), "green");
|
||||
for (Vec2f &p : result2[i])
|
||||
svg.draw((p * 1e6).cast<coord_t>(), "green", 1e6);
|
||||
}//*/
|
||||
}
|
||||
|
||||
TEST_CASE("Small islands should be supported in center", "[SupGen][VoronoiSkeleton]")
|
||||
{
|
||||
double size = 3e7;
|
||||
|
Loading…
x
Reference in New Issue
Block a user