mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 02:16:02 +08:00
Fixing crashes with objects residing at large world coordinate values
fixes issue SPE-1844
This commit is contained in:
parent
62c64fce2d
commit
9bb5bdb80f
@ -262,6 +262,47 @@ Transform3d YStriderVBedHandler::get_physical_bed_trafo(int bed_index) const
|
||||
return tr;
|
||||
}
|
||||
|
||||
Vec2i GridStriderVBedHandler::raw2grid(int bed_idx) const
|
||||
{
|
||||
Vec2i ret{bed_idx % ColsOutside, bed_idx / ColsOutside};
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int GridStriderVBedHandler::grid2raw(const Vec2i &crd) const
|
||||
{
|
||||
assert(crd.x() < ColsOutside - 1 && crd.y() < ColsOutside - 1);
|
||||
|
||||
return crd.y() * ColsOutside + crd.x();
|
||||
}
|
||||
|
||||
int GridStriderVBedHandler::get_bed_index(const VBedPlaceable &obj) const
|
||||
{
|
||||
Vec2i crd = {m_xstrider.get_bed_index(obj), m_ystrider.get_bed_index(obj)};
|
||||
|
||||
return grid2raw(crd);
|
||||
}
|
||||
|
||||
bool GridStriderVBedHandler::assign_bed(VBedPlaceable &inst, int bed_idx)
|
||||
{
|
||||
Vec2i crd = raw2grid(bed_idx);
|
||||
|
||||
bool retx = m_xstrider.assign_bed(inst, crd.x());
|
||||
bool rety = m_ystrider.assign_bed(inst, crd.y());
|
||||
|
||||
return retx && rety;
|
||||
}
|
||||
|
||||
Transform3d GridStriderVBedHandler::get_physical_bed_trafo(int bed_idx) const
|
||||
{
|
||||
Vec2i crd = raw2grid(bed_idx);
|
||||
|
||||
Transform3d ret = m_xstrider.get_physical_bed_trafo(crd.x()) *
|
||||
m_ystrider.get_physical_bed_trafo(crd.y());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
FixedSelection::FixedSelection(const Model &m) : m_wp{true}
|
||||
{
|
||||
m_seldata.resize(m.objects.size());
|
||||
@ -805,7 +846,7 @@ std::unique_ptr<VirtualBedHandler> VirtualBedHandler::create(const ExtendedBed &
|
||||
if (is_infinite_bed(bed)) {
|
||||
ret = std::make_unique<PhysicalOnlyVBedHandler>();
|
||||
} else {
|
||||
// The gap between logical beds in the x axis expressed in ratio of
|
||||
// The gap between logical beds expressed in ratio of
|
||||
// the current bed width.
|
||||
constexpr double LogicalBedGap = 1. / 10.;
|
||||
|
||||
@ -814,7 +855,7 @@ std::unique_ptr<VirtualBedHandler> VirtualBedHandler::create(const ExtendedBed &
|
||||
|
||||
auto bedwidth = bedbb.size().x();
|
||||
coord_t xgap = LogicalBedGap * bedwidth;
|
||||
ret = std::make_unique<XStriderVBedHandler>(bedbb, xgap);
|
||||
ret = std::make_unique<GridStriderVBedHandler>(bedbb, xgap);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -330,6 +330,35 @@ public:
|
||||
Transform3d get_physical_bed_trafo(int bed_index) const override;
|
||||
};
|
||||
|
||||
class GridStriderVBedHandler: public VirtualBedHandler
|
||||
{
|
||||
// This vbed handler defines a grid of virtual beds with a large number
|
||||
// of columns so that it behaves as XStrider for regular cases.
|
||||
// The goal is to handle objects residing at world coordinates
|
||||
// not representable with scaled coordinates. Combining XStrider with
|
||||
// YStrider takes care of the X and Y axis to be mapped into the physical
|
||||
// bed's coordinate region (which is representable in scaled coords)
|
||||
static const int ColsOutside = std::sqrt(std::numeric_limits<int>::max());
|
||||
|
||||
XStriderVBedHandler m_xstrider;
|
||||
YStriderVBedHandler m_ystrider;
|
||||
|
||||
public:
|
||||
GridStriderVBedHandler(const BoundingBox &bedbb,
|
||||
coord_t gap)
|
||||
: m_xstrider{bedbb, gap}
|
||||
, m_ystrider{bedbb, gap}
|
||||
{}
|
||||
|
||||
Vec2i raw2grid(int bedidx) const;
|
||||
int grid2raw(const Vec2i &crd) const;
|
||||
|
||||
int get_bed_index(const VBedPlaceable &obj) const override;
|
||||
bool assign_bed(VBedPlaceable &inst, int bed_idx) override;
|
||||
|
||||
Transform3d get_physical_bed_trafo(int bed_index) const override;
|
||||
};
|
||||
|
||||
std::vector<size_t> selected_object_indices(const SelectionMask &sm);
|
||||
std::vector<size_t> selected_instance_indices(int obj_idx, const SelectionMask &sm);
|
||||
|
||||
|
@ -326,10 +326,18 @@ auto create_vbed_handler<Slic3r::arr2::YStriderVBedHandler>(const Slic3r::Boundi
|
||||
return Slic3r::arr2::YStriderVBedHandler{bedbb, gap};
|
||||
}
|
||||
|
||||
TEMPLATE_TEST_CASE("Common virtual bed handlers", "[arrange2][integration][vbeds]",
|
||||
Slic3r::arr2::PhysicalOnlyVBedHandler,
|
||||
Slic3r::arr2::XStriderVBedHandler,
|
||||
Slic3r::arr2::YStriderVBedHandler)
|
||||
template<>
|
||||
auto create_vbed_handler<Slic3r::arr2::GridStriderVBedHandler>(const Slic3r::BoundingBox &bedbb, coord_t gap)
|
||||
{
|
||||
return Slic3r::arr2::GridStriderVBedHandler{bedbb, gap};
|
||||
}
|
||||
|
||||
TEMPLATE_TEST_CASE("Common virtual bed handlers",
|
||||
"[arrange2][integration][vbeds]",
|
||||
Slic3r::arr2::PhysicalOnlyVBedHandler,
|
||||
Slic3r::arr2::XStriderVBedHandler,
|
||||
Slic3r::arr2::YStriderVBedHandler,
|
||||
Slic3r::arr2::GridStriderVBedHandler)
|
||||
{
|
||||
using namespace Slic3r;
|
||||
using VBP = arr2::VBedPlaceableMI;
|
||||
@ -413,7 +421,7 @@ TEMPLATE_TEST_CASE("Common virtual bed handlers", "[arrange2][integration][vbeds
|
||||
WHEN ("moving back to the physical bed")
|
||||
{
|
||||
auto &mi_back_to_phys = *model.objects.front()->add_instance(mi_to_move);
|
||||
bool moved_back_to_physical = vbedh->assign_bed(VBP{mi_back_to_phys}, 0);
|
||||
bool moved_back_to_physical = vbedh->assign_bed(VBP{mi_back_to_phys}, arr2::PhysicalBedId);
|
||||
|
||||
THEN("model instance should actually move back to the physical bed")
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user