mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-05-30 10:04:35 +08:00
Bed shape detection in progress
This commit is contained in:
parent
e7e212cb52
commit
8da8ecb415
@ -292,6 +292,7 @@ public:
|
|||||||
|
|
||||||
template<class...Args> inline IndexedPackGroup operator()(Args&&...args) {
|
template<class...Args> inline IndexedPackGroup operator()(Args&&...args) {
|
||||||
areacache_.clear();
|
areacache_.clear();
|
||||||
|
rtree_.clear();
|
||||||
return pck_.arrangeIndexed(std::forward<Args>(args)...);
|
return pck_.arrangeIndexed(std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -440,16 +441,157 @@ ShapeData2D projectModelFromTop(const Slic3r::Model &model) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum BedShapeHint {
|
class Circle {
|
||||||
|
Point center_;
|
||||||
|
double radius_;
|
||||||
|
public:
|
||||||
|
|
||||||
|
inline Circle(): center_(0, 0), radius_(std::nan("")) {}
|
||||||
|
inline Circle(const Point& c, double r): center_(c), radius_(r) {}
|
||||||
|
|
||||||
|
inline double radius() const { return radius_; }
|
||||||
|
inline const Point& center() const { return center_; }
|
||||||
|
inline operator bool() { return std::isnan(radius_); }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Circle circle(std::array<Point, 3> P) {
|
||||||
|
|
||||||
|
using Coord = Point::coord_type;
|
||||||
|
using std::pow;
|
||||||
|
using std::abs;
|
||||||
|
using std::round;
|
||||||
|
using std::nan;
|
||||||
|
|
||||||
|
auto getX = [](const Point& p) { return p.x; };
|
||||||
|
auto getY = [](const Point& p) { return p.y; };
|
||||||
|
|
||||||
|
auto distance = [](const Point& p1, const Point& p2) {
|
||||||
|
return abs(p1.distance_to(p2));
|
||||||
|
};
|
||||||
|
|
||||||
|
static const auto E = 10.0/SCALING_FACTOR;
|
||||||
|
|
||||||
|
auto x1 = getX(P[0]), y1 = getY(P[0]);
|
||||||
|
auto x2 = getX(P[1]), y2 = getY(P[1]);
|
||||||
|
auto x3 = getX(P[2]), y3 = getY(P[2]);
|
||||||
|
|
||||||
|
|
||||||
|
auto A_div = (x2 - x1);
|
||||||
|
auto B_div = (x3 - x2);
|
||||||
|
if(A_div == 0 || B_div == 0) return Circle();
|
||||||
|
|
||||||
|
auto A = (y2 - y1)/A_div;
|
||||||
|
auto B = (y2 - y3)/B_div;
|
||||||
|
auto C = (-pow(x1, 2) - pow(y1, 2) + pow(x2, 2) + pow(y2, 2))/(2*(x2 - x1));
|
||||||
|
auto D = (pow(x2, 2) + pow(y1, 2) - pow(x3, 2) - pow(y3, 2))/(2*(x3 - x2));
|
||||||
|
|
||||||
|
auto cy = (C + D)/(A + B);
|
||||||
|
auto cx = B*cy - D;
|
||||||
|
|
||||||
|
Point cc = {Coord(round(cx)), Coord(round(cy))};
|
||||||
|
auto d = distance(cc, P[0]);
|
||||||
|
auto d2 = distance(cc, P[1]);
|
||||||
|
auto d3 = distance(cc, P[2]);
|
||||||
|
|
||||||
|
auto e1 = abs(d - d2);
|
||||||
|
auto e2 = abs(d - d3);
|
||||||
|
|
||||||
|
if(e1 > E || e2 > E) return Circle();
|
||||||
|
|
||||||
|
return { cc, d };
|
||||||
|
}
|
||||||
|
|
||||||
|
Circle isCircle(const Polyline& p) {
|
||||||
|
|
||||||
|
using std::abs;
|
||||||
|
|
||||||
|
auto& pp = p.points;
|
||||||
|
static const double E = 10/SCALING_FACTOR;
|
||||||
|
double radius = 0;
|
||||||
|
bool ret = true;
|
||||||
|
Circle c;
|
||||||
|
for(auto i = 0; i < pp.size() - 3 && ret; i += 3) {
|
||||||
|
c = circle({pp[i], pp[i+1], pp[i+2]});
|
||||||
|
if(c || abs(radius - c.radius()) >= E) ret = false;
|
||||||
|
else radius = c.radius();
|
||||||
|
}
|
||||||
|
|
||||||
|
// auto rem = pp.size() % 3;
|
||||||
|
|
||||||
|
// if(ret && rem > 0) {
|
||||||
|
// std::array<Point, 3> remarr;
|
||||||
|
|
||||||
|
// auto i = 0;
|
||||||
|
// for(i = 0; i < rem; i++) remarr[i] = *(pp.rbegin() - i);
|
||||||
|
// while(i < 3) remarr[i] = pp[i++];
|
||||||
|
// c = circle(remarr);
|
||||||
|
// if(c || abs(radius - c.radius()) >= E) ret = false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
if(!ret) c = Circle();
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class BedShapeType {
|
||||||
BOX,
|
BOX,
|
||||||
CIRCLE,
|
CIRCLE,
|
||||||
IRREGULAR,
|
IRREGULAR,
|
||||||
WHO_KNOWS
|
WHO_KNOWS
|
||||||
};
|
};
|
||||||
|
|
||||||
BedShapeHint bedShape(const Slic3r::Polyline& /*bed*/) {
|
struct BedShapeHint {
|
||||||
|
BedShapeType type;
|
||||||
|
/*union*/ struct { // I know but who cares...
|
||||||
|
Circle circ;
|
||||||
|
BoundingBox box;
|
||||||
|
Polyline polygon;
|
||||||
|
} shape;
|
||||||
|
};
|
||||||
|
|
||||||
|
BedShapeHint bedShape(const Polyline& bed) {
|
||||||
|
static const double E = 10/SCALING_FACTOR;
|
||||||
|
|
||||||
|
BedShapeHint ret;
|
||||||
|
|
||||||
|
auto width = [](const BoundingBox& box) {
|
||||||
|
return box.max.x - box.min.x;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto height = [](const BoundingBox& box) {
|
||||||
|
return box.max.y - box.min.y;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto area = [&width, &height](const BoundingBox& box) {
|
||||||
|
return width(box) * height(box);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto poly_area = [](Polyline p) {
|
||||||
|
Polygon pp; pp.points.reserve(p.points.size() + 1);
|
||||||
|
pp.points = std::move(p.points);
|
||||||
|
pp.points.emplace_back(pp.points.front());
|
||||||
|
return std::abs(pp.area());
|
||||||
|
};
|
||||||
|
|
||||||
|
auto bb = bed.bounding_box();
|
||||||
|
if(std::abs(area(bb) - poly_area(bed)) < E) {
|
||||||
|
ret.type = BedShapeType::BOX;
|
||||||
|
ret.shape.box = bb;
|
||||||
|
std::cout << "BOX" << std::endl;
|
||||||
|
}
|
||||||
|
else if(auto c = isCircle(bed)) {
|
||||||
|
ret.type = BedShapeType::CIRCLE;
|
||||||
|
ret.shape.circ = c;
|
||||||
|
std::cout << "Circle" << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "Polygon" << std::endl;
|
||||||
|
ret.type = BedShapeType::IRREGULAR;
|
||||||
|
ret.shape.polygon = bed;
|
||||||
|
}
|
||||||
|
|
||||||
// Determine the bed shape by hand
|
// Determine the bed shape by hand
|
||||||
return BOX;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void applyResult(
|
void applyResult(
|
||||||
@ -525,7 +667,10 @@ bool arrange(Model &model, coordf_t min_obj_distance,
|
|||||||
});
|
});
|
||||||
|
|
||||||
IndexedPackGroup result;
|
IndexedPackGroup result;
|
||||||
BoundingBox bbb(bed.points);
|
|
||||||
|
if(bedhint.type == BedShapeType::WHO_KNOWS) bedhint = bedShape(bed);
|
||||||
|
|
||||||
|
BoundingBox bbb(bed);
|
||||||
|
|
||||||
auto binbb = Box({
|
auto binbb = Box({
|
||||||
static_cast<libnest2d::Coord>(bbb.min.x),
|
static_cast<libnest2d::Coord>(bbb.min.x),
|
||||||
@ -536,8 +681,8 @@ bool arrange(Model &model, coordf_t min_obj_distance,
|
|||||||
static_cast<libnest2d::Coord>(bbb.max.y)
|
static_cast<libnest2d::Coord>(bbb.max.y)
|
||||||
});
|
});
|
||||||
|
|
||||||
switch(bedhint) {
|
switch(bedhint.type) {
|
||||||
case BOX: {
|
case BedShapeType::BOX: {
|
||||||
|
|
||||||
// Create the arranger for the box shaped bed
|
// Create the arranger for the box shaped bed
|
||||||
AutoArranger<Box> arrange(binbb, min_obj_distance, progressind);
|
AutoArranger<Box> arrange(binbb, min_obj_distance, progressind);
|
||||||
@ -547,10 +692,11 @@ bool arrange(Model &model, coordf_t min_obj_distance,
|
|||||||
result = arrange(shapes.begin(), shapes.end());
|
result = arrange(shapes.begin(), shapes.end());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CIRCLE:
|
case BedShapeType::CIRCLE:
|
||||||
break;
|
break;
|
||||||
case IRREGULAR:
|
case BedShapeType::IRREGULAR:
|
||||||
case WHO_KNOWS: {
|
case BedShapeType::WHO_KNOWS: {
|
||||||
|
|
||||||
using P = libnest2d::PolygonImpl;
|
using P = libnest2d::PolygonImpl;
|
||||||
|
|
||||||
auto ctour = Slic3rMultiPoint_to_ClipperPath(bed);
|
auto ctour = Slic3rMultiPoint_to_ClipperPath(bed);
|
||||||
|
@ -288,6 +288,7 @@ const PrintConfig &PrintController::config() const
|
|||||||
return print_->config;
|
return print_->config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void AppController::arrange_model()
|
void AppController::arrange_model()
|
||||||
{
|
{
|
||||||
auto ftr = std::async(
|
auto ftr = std::async(
|
||||||
@ -324,10 +325,14 @@ void AppController::arrange_model()
|
|||||||
if(pind) pind->update(0, _(L("Arranging objects...")));
|
if(pind) pind->update(0, _(L("Arranging objects...")));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
arr::BedShapeHint hint;
|
||||||
|
// TODO: from Sasha from GUI
|
||||||
|
hint.type = arr::BedShapeType::WHO_KNOWS;
|
||||||
|
|
||||||
arr::arrange(*model_,
|
arr::arrange(*model_,
|
||||||
min_obj_distance,
|
min_obj_distance,
|
||||||
bed,
|
bed,
|
||||||
arr::BOX,
|
hint,
|
||||||
false, // create many piles not just one pile
|
false, // create many piles not just one pile
|
||||||
[pind, count](unsigned rem) {
|
[pind, count](unsigned rem) {
|
||||||
if(pind)
|
if(pind)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user