Refactored Lightning infill to get rid of unnecessary std::list and std::unordered_map, which was slow.
This commit is contained in:
parent
3e5272868d
commit
5205753787
@ -35,16 +35,18 @@ DistanceField::DistanceField(const coord_t& radius, const Polygons& current_outl
|
|||||||
assert(m_unsupported_points_bbox.contains(p));
|
assert(m_unsupported_points_bbox.contains(p));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_unsupported_points.sort([&radius](const UnsupportedCell &a, const UnsupportedCell &b) {
|
std::stable_sort(m_unsupported_points.begin(), m_unsupported_points.end(), [&radius](const UnsupportedCell &a, const UnsupportedCell &b) {
|
||||||
constexpr coord_t prime_for_hash = 191;
|
constexpr coord_t prime_for_hash = 191;
|
||||||
return std::abs(b.dist_to_boundary - a.dist_to_boundary) > radius ?
|
return std::abs(b.dist_to_boundary - a.dist_to_boundary) > radius ?
|
||||||
a.dist_to_boundary < b.dist_to_boundary :
|
a.dist_to_boundary < b.dist_to_boundary :
|
||||||
(PointHash{}(a.loc) % prime_for_hash) < (PointHash{}(b.loc) % prime_for_hash);
|
(PointHash{}(a.loc) % prime_for_hash) < (PointHash{}(b.loc) % prime_for_hash);
|
||||||
});
|
});
|
||||||
for (auto it = m_unsupported_points.begin(); it != m_unsupported_points.end(); ++it) {
|
|
||||||
UnsupportedCell& cell = *it;
|
m_unsupported_points_erased.resize(m_unsupported_points.size());
|
||||||
m_unsupported_points_grid.emplace(this->to_grid_point(cell.loc), it);
|
std::fill(m_unsupported_points_erased.begin(), m_unsupported_points_erased.end(), false);
|
||||||
}
|
|
||||||
|
m_unsupported_points_grid.initialize(m_unsupported_points, [&self = std::as_const(*this)](const Point &p) -> Point { return self.to_grid_point(p); });
|
||||||
|
|
||||||
// Because the distance between two points is at least one axis equal to m_cell_size, every cell
|
// Because the distance between two points is at least one axis equal to m_cell_size, every cell
|
||||||
// in m_unsupported_points_grid contains exactly one point.
|
// in m_unsupported_points_grid contains exactly one point.
|
||||||
assert(m_unsupported_points.size() == m_unsupported_points_grid.size());
|
assert(m_unsupported_points.size() == m_unsupported_points_grid.size());
|
||||||
@ -96,12 +98,11 @@ void DistanceField::update(const Point& to_node, const Point& added_leaf)
|
|||||||
}
|
}
|
||||||
// Inside a circle at the end of the new leaf, or inside a rotated rectangle.
|
// Inside a circle at the end of the new leaf, or inside a rotated rectangle.
|
||||||
// Remove unsupported leafs at this grid location.
|
// Remove unsupported leafs at this grid location.
|
||||||
if (auto it = m_unsupported_points_grid.find(grid_addr); it != m_unsupported_points_grid.end()) {
|
if (const size_t cell_idx = m_unsupported_points_grid.find_cell_idx(grid_addr); cell_idx != std::numeric_limits<size_t>::max()) {
|
||||||
std::list<UnsupportedCell>::iterator& list_it = it->second;
|
const UnsupportedCell &cell = m_unsupported_points[cell_idx];
|
||||||
UnsupportedCell& cell = *list_it;
|
|
||||||
if ((cell.loc - added_leaf).cast<int64_t>().squaredNorm() <= m_supporting_radius2) {
|
if ((cell.loc - added_leaf).cast<int64_t>().squaredNorm() <= m_supporting_radius2) {
|
||||||
m_unsupported_points.erase(list_it);
|
m_unsupported_points_erased[cell_idx] = true;
|
||||||
m_unsupported_points_grid.erase(it);
|
m_unsupported_points_grid.mark_erased(grid_addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,11 +38,17 @@ public:
|
|||||||
* \return ``true`` if successful, or ``false`` if there are no more points
|
* \return ``true`` if successful, or ``false`` if there are no more points
|
||||||
* to consider.
|
* to consider.
|
||||||
*/
|
*/
|
||||||
bool tryGetNextPoint(Point* p) const {
|
bool tryGetNextPoint(Point *out_unsupported_location, size_t *out_unsupported_cell_idx, const size_t start_idx = 0) const
|
||||||
if (m_unsupported_points.empty())
|
{
|
||||||
return false;
|
for (size_t point_idx = start_idx; point_idx < m_unsupported_points.size(); ++point_idx) {
|
||||||
*p = m_unsupported_points.front().loc;
|
if (!m_unsupported_points_erased[point_idx]) {
|
||||||
return true;
|
*out_unsupported_cell_idx = point_idx;
|
||||||
|
*out_unsupported_location = m_unsupported_points[point_idx].loc;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -87,7 +93,8 @@ protected:
|
|||||||
/*!
|
/*!
|
||||||
* Cells which still need to be supported at some point.
|
* Cells which still need to be supported at some point.
|
||||||
*/
|
*/
|
||||||
std::list<UnsupportedCell> m_unsupported_points;
|
std::vector<UnsupportedCell> m_unsupported_points;
|
||||||
|
std::vector<bool> m_unsupported_points_erased;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* BoundingBox of all points in m_unsupported_points. Used for mapping of sign integer numbers to positive integer numbers.
|
* BoundingBox of all points in m_unsupported_points. Used for mapping of sign integer numbers to positive integer numbers.
|
||||||
@ -98,7 +105,84 @@ protected:
|
|||||||
* Links the unsupported points to a grid point, so that we can quickly look
|
* Links the unsupported points to a grid point, so that we can quickly look
|
||||||
* up the cell belonging to a certain position in the grid.
|
* up the cell belonging to a certain position in the grid.
|
||||||
*/
|
*/
|
||||||
std::unordered_map<Point, std::list<UnsupportedCell>::iterator, PointHash> m_unsupported_points_grid;
|
|
||||||
|
class UnsupportedPointsGrid
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
UnsupportedPointsGrid() = default;
|
||||||
|
void initialize(const std::vector<UnsupportedCell> &unsupported_points, const std::function<Point(const Point &)> &map_cell_to_grid)
|
||||||
|
{
|
||||||
|
if (unsupported_points.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
BoundingBox unsupported_points_bbox;
|
||||||
|
for (const UnsupportedCell &cell : unsupported_points)
|
||||||
|
unsupported_points_bbox.merge(cell.loc);
|
||||||
|
|
||||||
|
m_size = unsupported_points.size();
|
||||||
|
m_grid_range = BoundingBox(map_cell_to_grid(unsupported_points_bbox.min), map_cell_to_grid(unsupported_points_bbox.max));
|
||||||
|
m_grid_size = m_grid_range.size() + Point::Ones();
|
||||||
|
|
||||||
|
m_data.assign(m_grid_size.y() * m_grid_size.x(), std::numeric_limits<size_t>::max());
|
||||||
|
m_data_erased.assign(m_grid_size.y() * m_grid_size.x(), true);
|
||||||
|
|
||||||
|
for (size_t cell_idx = 0; cell_idx < unsupported_points.size(); ++cell_idx) {
|
||||||
|
const size_t flat_idx = map_to_flat_array(map_cell_to_grid(unsupported_points[cell_idx].loc));
|
||||||
|
assert(m_data[flat_idx] == std::numeric_limits<size_t>::max());
|
||||||
|
m_data[flat_idx] = cell_idx;
|
||||||
|
m_data_erased[flat_idx] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const { return m_size; }
|
||||||
|
|
||||||
|
size_t find_cell_idx(const Point &grid_addr)
|
||||||
|
{
|
||||||
|
if (!m_grid_range.contains(grid_addr))
|
||||||
|
return std::numeric_limits<size_t>::max();
|
||||||
|
|
||||||
|
if (const size_t flat_idx = map_to_flat_array(grid_addr); !m_data_erased[flat_idx]) {
|
||||||
|
assert(m_data[flat_idx] != std::numeric_limits<size_t>::max());
|
||||||
|
return m_data[flat_idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::numeric_limits<size_t>::max();
|
||||||
|
}
|
||||||
|
|
||||||
|
void mark_erased(const Point &grid_addr)
|
||||||
|
{
|
||||||
|
assert(m_grid_range.contains(grid_addr));
|
||||||
|
if (!m_grid_range.contains(grid_addr))
|
||||||
|
return;
|
||||||
|
|
||||||
|
const size_t flat_idx = map_to_flat_array(grid_addr);
|
||||||
|
assert(!m_data_erased[flat_idx] && m_data[flat_idx] != std::numeric_limits<size_t>::max());
|
||||||
|
assert(m_size != 0);
|
||||||
|
|
||||||
|
m_data_erased[flat_idx] = true;
|
||||||
|
--m_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t m_size = 0;
|
||||||
|
|
||||||
|
BoundingBox m_grid_range;
|
||||||
|
Point m_grid_size;
|
||||||
|
|
||||||
|
std::vector<size_t> m_data;
|
||||||
|
std::vector<bool> m_data_erased;
|
||||||
|
|
||||||
|
inline size_t map_to_flat_array(const Point &loc) const
|
||||||
|
{
|
||||||
|
const Point offset_loc = loc - m_grid_range.min;
|
||||||
|
const size_t flat_idx = m_grid_size.x() * offset_loc.y() + offset_loc.x();
|
||||||
|
assert(offset_loc.x() >= 0 && offset_loc.y() >= 0);
|
||||||
|
assert(flat_idx < m_grid_size.y() * m_grid_size.x());
|
||||||
|
return flat_idx;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
UnsupportedPointsGrid m_unsupported_points_grid;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Maps the point to the grid coordinates.
|
* Maps the point to the grid coordinates.
|
||||||
|
@ -56,8 +56,9 @@ void Layer::generateNewTrees
|
|||||||
|
|
||||||
// Until no more points need to be added to support all:
|
// Until no more points need to be added to support all:
|
||||||
// Determine next point from tree/outline areas via distance-field
|
// Determine next point from tree/outline areas via distance-field
|
||||||
Point unsupported_location;
|
size_t unsupported_cell_idx = 0;
|
||||||
while (distance_field.tryGetNextPoint(&unsupported_location)) {
|
Point unsupported_location;
|
||||||
|
while (distance_field.tryGetNextPoint(&unsupported_location, &unsupported_cell_idx, unsupported_cell_idx)) {
|
||||||
throw_on_cancel_callback();
|
throw_on_cancel_callback();
|
||||||
GroundingLocation grounding_loc = getBestGroundingLocation(
|
GroundingLocation grounding_loc = getBestGroundingLocation(
|
||||||
unsupported_location, current_outlines, current_outlines_bbox, outlines_locator, supporting_radius, wall_supporting_radius, tree_node_locator);
|
unsupported_location, current_outlines, current_outlines_bbox, outlines_locator, supporting_radius, wall_supporting_radius, tree_node_locator);
|
||||||
|
Loading…
Reference in New Issue
Block a user