Fixing crashes with objects residing at large world coordinate values

fixes issue SPE-1844
This commit is contained in:
tamasmeszaros 2023-08-15 17:03:41 +02:00
parent 62c64fce2d
commit 9bb5bdb80f
3 changed files with 85 additions and 7 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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")
{