OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
marchsq::__impl::Grid< Rst > Class Template Reference

#include </home/runner/work/OrcaSlicer/OrcaSlicer/src/libslic3r/MarchingSquares.hpp>

Collaboration diagram for marchsq::__impl::Grid< Rst >:

Classes

struct  CellIt
struct  Edge

Public Member Functions

 Grid (const Rst &rst, const Coord &window)
template<class ExecutionPolicy>
void tag_grid (ExecutionPolicy &&policy, TRasterValue< Rst > isoval)
std::vector< Ring > scan_rings ()
template<class ExecutionPolicy>
void interpolate_rings (ExecutionPolicy &&policy, std::vector< Ring > &rings, TRasterValue< Rst > isov)
std::ostream & streamtags (std::ostream &os)
std::ostream & streamdirs (std::ostream &os)

Private Member Functions

Coord rastercoord (const Coord &crd) const
Coord bl (const Coord &crd) const
Coord br (const Coord &crd) const
Coord tr (const Coord &crd) const
Coord tl (const Coord &crd) const
bool is_within (const Coord &crd) const
uint32_t get_tags_block32 (const size_t bidx, const TRasterValue< Rst > v) const
uint32_t get_dirs_block8 (const size_t bidx) const
uint32_t get_tags9 (size_t gidx) const
void clr_dirs (const size_t gidx, const Dir d)
Dir get_dirs (const size_t gidx) const
Coord coord (size_t i) const
size_t seq (const Coord &crd) const
size_t stepidx (const size_t idx, const Dir d) const
size_t search_start_cell (size_t gidx=0) const
Dir next_dir (size_t idx, Dir prev=Dir::all) const
Edge _edge (const Coord &ringvertex) const
Edge edge (const Coord &ringvertex) const
void interpolate_edge (Coord &ecrd, TRasterValue< Rst > isoval) const

Private Attributes

const Rst * m_rst = nullptr
Coord m_window
Coord m_rastsize
Coord m_gridsize
size_t m_gridlen
std::vector< uint32_t > m_tags
std::vector< uint32_t > m_dirs

Detailed Description

template<class Rst>
class marchsq::__impl::Grid< Rst >

Class Documentation

◆ marchsq::__impl::Grid::Edge

struct marchsq::__impl::Grid::Edge
template<class Rst>
struct marchsq::__impl::Grid< Rst >::Edge
Collaboration diagram for marchsq::__impl::Grid< Rst >::Edge:
Class Members
CellIt from
CellIt to

Constructor & Destructor Documentation

◆ Grid()

template<class Rst>
marchsq::__impl::Grid< Rst >::Grid ( const Rst & rst,
const Coord & window )
inlineexplicit
524 : m_rst{&rst}
526 , m_rastsize{static_cast<long>(rows(rst)), static_cast<long>(cols(rst))}
527 , m_gridsize{2 + m_rastsize.r / m_window.r, 2 + m_rastsize.c / m_window.c}
528 , m_gridlen{static_cast<size_t>(m_gridsize.r * m_gridsize.c)}
529 , m_tags(m_gridlen / 32 + 1, 0) // 1 bit per tag means 32 per uint32_t.
530 , m_dirs(m_gridlen / 8 + 1, 0) // 4 bits per cell means 32/4=8 per uint32_t.
531 {}
Definition MarchingSquares.hpp:224
std::vector< uint32_t > m_dirs
Definition MarchingSquares.hpp:229
std::vector< uint32_t > m_tags
Definition MarchingSquares.hpp:228
const Rst * m_rst
Definition MarchingSquares.hpp:225
Coord m_rastsize
Definition MarchingSquares.hpp:226
Coord m_gridsize
Definition MarchingSquares.hpp:226
Coord m_window
Definition MarchingSquares.hpp:226
size_t m_gridlen
Definition MarchingSquares.hpp:227
size_t cols(const T &raster)
Definition MarchingSquares.hpp:173
size_t rows(const T &raster)
Definition MarchingSquares.hpp:171

References marchsq::__impl::cols(), m_dirs, m_gridlen, m_gridsize, m_rastsize, m_rst, m_tags, m_window, and marchsq::__impl::rows().

Here is the call graph for this function:

Member Function Documentation

◆ _edge()

template<class Rst>
Edge marchsq::__impl::Grid< Rst >::_edge ( const Coord & ringvertex) const
inlineprivate
478 {
479 size_t idx = ringvertex.r;
480 Coord cell = coord(idx);
481 Dir d = Dir(ringvertex.c);
482
483 switch (d) {
484 case Dir::left: return {{tl(cell), Dir::down, m_rst}, {bl(cell)}};
485 case Dir::down: return {{bl(cell), Dir::right, m_rst}, {br(cell)}};
486 case Dir::right: return {{br(cell), Dir::up, m_rst}, {tr(cell)}};
487 case Dir::up: return {{tr(cell), Dir::left, m_rst}, {tl(cell)}};
488 default: assert(false);
489 }
490 return {};
491 }
Coord br(const Coord &crd) const
Definition MarchingSquares.hpp:240
Coord bl(const Coord &crd) const
Definition MarchingSquares.hpp:239
Coord coord(size_t i) const
Definition MarchingSquares.hpp:327
Coord tl(const Coord &crd) const
Definition MarchingSquares.hpp:242
Coord tr(const Coord &crd) const
Definition MarchingSquares.hpp:241
Dir
Definition MarchingSquares.hpp:186

References bl(), br(), marchsq::Coord::c, coord(), marchsq::__impl::down, marchsq::__impl::left, m_rst, marchsq::Coord::r, marchsq::__impl::right, tl(), tr(), and marchsq::__impl::up.

Referenced by edge().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ bl()

template<class Rst>
Coord marchsq::__impl::Grid< Rst >::bl ( const Coord & crd) const
inlineprivate
239{ return tl(crd) + Coord{m_window.r, 0}; }

References m_window, and tl().

Referenced by _edge().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ br()

template<class Rst>
Coord marchsq::__impl::Grid< Rst >::br ( const Coord & crd) const
inlineprivate
240{ return tl(crd) + Coord{m_window.r, m_window.c}; }

References m_window, and tl().

Referenced by _edge().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ clr_dirs()

template<class Rst>
void marchsq::__impl::Grid< Rst >::clr_dirs ( const size_t gidx,
const Dir d )
inlineprivate
308 {
310 size_t i = gidx / 8; // the dirs block index
311 int o = (gidx % 8); // the dirs block offset
312
313 m_dirs[i] &= ~(static_cast<uint32_t>(d) << (o * 4));
314 }

References m_dirs, and m_gridlen.

Referenced by scan_rings().

Here is the caller graph for this function:

◆ coord()

template<class Rst>
Coord marchsq::__impl::Grid< Rst >::coord ( size_t i) const
inlineprivate
327{ return {long(i) / m_gridsize.c, long(i) % m_gridsize.c}; }

References m_gridsize.

Referenced by _edge(), and get_tags_block32().

Here is the caller graph for this function:

◆ edge()

template<class Rst>
Edge marchsq::__impl::Grid< Rst >::edge ( const Coord & ringvertex) const
inlineprivate
494 {
496 e.to.dir = e.from.dir;
497 ++e.to;
498
499 e.from.crd.r = std::clamp(e.from.crd.r, 0l, m_rastsize.r - 1);
500 e.from.crd.c = std::clamp(e.from.crd.c, 0l, m_rastsize.c - 1);
501 e.to.crd.r = std::clamp(e.to.crd.r, 0l, m_rastsize.r);
502 e.to.crd.c = std::clamp(e.to.crd.c, 0l, m_rastsize.c);
503 return e;
504 }
Edge _edge(const Coord &ringvertex) const
Definition MarchingSquares.hpp:477
Definition MarchingSquares.hpp:473

References _edge(), marchsq::Coord::c, marchsq::__impl::Grid< Rst >::CellIt::crd, marchsq::__impl::Grid< Rst >::CellIt::dir, marchsq::__impl::Grid< Rst >::Edge::from, m_rastsize, marchsq::Coord::r, and marchsq::__impl::Grid< Rst >::Edge::to.

Referenced by interpolate_edge().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_dirs()

template<class Rst>
Dir marchsq::__impl::Grid< Rst >::get_dirs ( const size_t gidx) const
inlineprivate
318 {
320 size_t i = gidx / 8; // the dirs block index
321 int o = (gidx % 8); // the dirs block offset
322
323 return Dir((m_dirs[i] >> (o * 4)) & 0b1111);
324 }

References m_dirs, and m_gridlen.

Referenced by next_dir(), and streamdirs().

Here is the caller graph for this function:

◆ get_dirs_block8()

template<class Rst>
uint32_t marchsq::__impl::Grid< Rst >::get_dirs_block8 ( const size_t bidx) const
inlineprivate
270 {
271 size_t gidx = bidx * 8;
272 uint32_t dirs = 0;
273
274 // Get the next 9 top-row tags at this grid index into the bottom 16
275 // bits, and the 9 bottom-row tags into the top 16 bits.
277 // Skip generating dirs if the tags are all 1's or all 0's.
278 if ((tags9 != 0) && (tags9 != 0x01ff01ff)) {
279 for (auto s = 0; s < 32; s += 4) {
280 uint8_t tags = (tags9 & 0b11) | ((tags9 >> 14) & 0b1100);
281 dirs |= NEXT_CCW[tags] << s;
282 tags9 >>= 1;
283 }
284 }
285 return dirs;
286 }
uint32_t get_tags9(size_t gidx) const
Definition MarchingSquares.hpp:289

References get_tags9(), m_gridsize, and marchsq::__impl::NEXT_CCW.

Here is the call graph for this function:

◆ get_tags9()

template<class Rst>
uint32_t marchsq::__impl::Grid< Rst >::get_tags9 ( size_t gidx) const
inlineprivate
290 {
291 uint32_t tags = 0; // the tags value.
292 size_t i = gidx / 32; // the tags block index
293 int o = gidx % 32; // the tags block offset
294
295 if (gidx < m_gridlen) {
296 // get the next 9 tags in the row.
297 tags = (m_tags[i] >> o) & 0x1ff;
298 // Some of the tags are in the next tags block.
299 if ((o > (32 - 9)) && ((i + 1) < m_tags.size())) {
300 tags |= (m_tags[i + 1] << (32 - o)) & 0x1ff;
301 }
302 }
303 return tags;
304 }

References m_gridlen, and m_tags.

Referenced by get_dirs_block8(), and streamtags().

Here is the caller graph for this function:

◆ get_tags_block32()

template<class Rst>
uint32_t marchsq::__impl::Grid< Rst >::get_tags_block32 ( const size_t bidx,
const TRasterValue< Rst > v ) const
inlineprivate
249 {
250 Coord gcrd = coord(bidx * 32); // position in grid coordinates of the block.
251 Coord rcrd = rastercoord(gcrd); // position in raster coordinates.
252 uint32_t tags = 0;
253 // Set a bit for each corner that has osoval > v.
254 for (uint32_t b = 1; b; b <<= 1) {
255 if (is_within(rcrd) && isoval(*m_rst, rcrd) > v)
256 tags |= b;
257 gcrd.c += 1;
258 rcrd.c += m_window.c;
259 // If we hit the end of the row, start on the next row.
260 if (gcrd.c >= m_gridsize.c) {
261 gcrd = Coord(gcrd.r + 1, 0);
263 }
264 }
265 return tags;
266 }
Coord rastercoord(const Coord &crd) const
Definition MarchingSquares.hpp:232
bool is_within(const Coord &crd) const
Definition MarchingSquares.hpp:245
TRasterValue< T > isoval(const T &rst, const Coord &crd)
Definition MarchingSquares.hpp:175

References marchsq::Coord::c, coord(), is_within(), marchsq::__impl::isoval(), m_gridsize, m_rst, m_window, marchsq::Coord::r, and rastercoord().

Here is the call graph for this function:

◆ interpolate_edge()

template<class Rst>
void marchsq::__impl::Grid< Rst >::interpolate_edge ( Coord & ecrd,
TRasterValue< Rst > isoval ) const
inlineprivate
507 {
508 // The ecrd must have a grid index in r and a direction in c.
509 assert((0 <= ecrd.r) && (ecrd.r < m_gridlen));
510 assert((ecrd.c == long(Dir::left)) || (ecrd.c == long(Dir::down)) || (ecrd.c == long(Dir::right)) || (ecrd.c == long(Dir::up)));
511 Edge e = edge(ecrd);
512 ecrd = std::lower_bound(e.from, e.to, isoval).crd;
513 // Shift bottom and right side points "out" by one to account for
514 // raster pixel width. Note "dir" is the direction of interpolation
515 // along the cell edge, not the next move direction.
516 if (e.from.dir == Dir::up)
517 ecrd.r += 1;
518 else if (e.from.dir == Dir::left)
519 ecrd.c += 1;
520 }
Edge edge(const Coord &ringvertex) const
Definition MarchingSquares.hpp:493

References marchsq::Coord::c, marchsq::__impl::Grid< Rst >::CellIt::dir, marchsq::__impl::down, edge(), marchsq::__impl::Grid< Rst >::Edge::from, marchsq::__impl::isoval(), marchsq::__impl::left, m_gridlen, marchsq::Coord::r, marchsq::__impl::right, marchsq::__impl::Grid< Rst >::Edge::to, and marchsq::__impl::up.

Here is the call graph for this function:

◆ interpolate_rings()

template<class Rst>
template<class ExecutionPolicy>
void marchsq::__impl::Grid< Rst >::interpolate_rings ( ExecutionPolicy && policy,
std::vector< Ring > & rings,
TRasterValue< Rst > isov )
inline
582 {
583 for_each_idx(std::forward<ExecutionPolicy>(policy), rings.begin(), rings.end(), [this, isov](Ring& ring, size_t) {
584 for (Coord& e : ring)
585 interpolate_edge(e, isov);
586 });
587 }
void for_each_idx(ExecutionPolicy &&policy, It from, It to, Fn &&fn)
Definition MarchingSquares.hpp:177

References marchsq::__impl::for_each_idx().

Here is the call graph for this function:

◆ is_within()

template<class Rst>
bool marchsq::__impl::Grid< Rst >::is_within ( const Coord & crd) const
inlineprivate
245{ return crd.r >= 0 && crd.r < m_rastsize.r && crd.c >= 0 && crd.c < m_rastsize.c; }

References marchsq::Coord::c, m_rastsize, and marchsq::Coord::r.

Referenced by get_tags_block32().

Here is the caller graph for this function:

◆ next_dir()

template<class Rst>
Dir marchsq::__impl::Grid< Rst >::next_dir ( size_t idx,
Dir prev = Dir::all ) const
inlineprivate
371 {
372 Dir next = get_dirs(idx);
373
374 // Treat ambiguous cases as two separate regions in one square. If
375 // there are two possible next directions, pick based on the prev
376 // direction. If prev=all we are starting a new line so pick the one
377 // that leads "forwards" (right or down) in the search.
378 switch (next) {
379 case Dir::leftright:
380 // We must be coming from up, down, or starting a new line.
381 assert(prev == Dir::up || prev == Dir::down || prev == Dir::all);
382 return (prev == Dir::up) ? Dir::left : Dir::right;
383 case Dir::updown:
384 // We must be coming from left, right, or starting a new line.
386 return (prev == Dir::right) ? Dir::up : Dir::down;
387 default:
388 // Next must be a single direction or none to stop.
390 return next;
391 }
392 }
Dir get_dirs(const size_t gidx) const
Definition MarchingSquares.hpp:317

References marchsq::__impl::all, marchsq::__impl::down, get_dirs(), marchsq::__impl::left, marchsq::__impl::leftright, marchsq::__impl::none, marchsq::__impl::right, marchsq::__impl::up, and marchsq::__impl::updown.

Referenced by scan_rings().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ rastercoord()

template<class Rst>
Coord marchsq::__impl::Grid< Rst >::rastercoord ( const Coord & crd) const
inlineprivate
233 {
234 // Note the -1 offset for the grid border around the raster area.
235 return {(crd.r - 1) * m_window.r, (crd.c - 1) * m_window.c};
236 }

References marchsq::Coord::c, m_window, and marchsq::Coord::r.

Referenced by get_tags_block32(), and tl().

Here is the caller graph for this function:

◆ scan_rings()

template<class Rst>
std::vector< Ring > marchsq::__impl::Grid< Rst >::scan_rings ( )
inline
551 {
553 size_t startidx = 0;
555 Ring ring;
556
557 size_t idx = startidx;
558 Dir next = next_dir(idx);
559 do {
560 // We should never touch a cell with no remaining directions
561 // until we get back to the start cell.
564 ring.emplace_back(ringvertex);
565 clr_dirs(idx, next);
566 idx = stepidx(idx, next);
567 next = next_dir(idx, next);
569 } while (idx != startidx);
570 // The start cell on returning should either have its directions
571 // cleared or have the second ambiguous direction.
573 if (ring.size() > 1)
574 rings.emplace_back(ring);
575 }
576 return rings;
577 }
void clr_dirs(const size_t gidx, const Dir d)
Definition MarchingSquares.hpp:307
size_t search_start_cell(size_t gidx=0) const
Definition MarchingSquares.hpp:346
Dir next_dir(size_t idx, Dir prev=Dir::all) const
Definition MarchingSquares.hpp:370
size_t stepidx(const size_t idx, const Dir d) const
Definition MarchingSquares.hpp:333

References clr_dirs(), marchsq::__impl::left, m_gridlen, next_dir(), marchsq::__impl::none, search_start_cell(), stepidx(), and marchsq::__impl::up.

Here is the call graph for this function:

◆ search_start_cell()

template<class Rst>
size_t marchsq::__impl::Grid< Rst >::search_start_cell ( size_t gidx = 0) const
inlineprivate
347 {
348 size_t i = gidx / 8; // The dirs block index.
349 int o = gidx % 8; // The dirs block offset.
350
351 // Skip cells without any unvisited edges.
352 while (i < m_dirs.size()) {
353 if (!m_dirs[i]) {
354 // Whole block is clear, advance to the next block;
355 i++;
356 o = 0;
357 } else {
358 // Block not clear, find the next non-zero tags in the block. Note
359 // all dirs before gidx are cleared, so any set bits must be in
360 // block offsets >= o, not before.
361 for (uint32_t m = 0b1111 << (o * 4); !(m_dirs[i] & m); m <<= 4)
362 o++;
363 break;
364 }
365 }
366 return i * 8 + o;
367 }

References m_dirs.

Referenced by scan_rings().

Here is the caller graph for this function:

◆ seq()

template<class Rst>
size_t marchsq::__impl::Grid< Rst >::seq ( const Coord & crd) const
inlineprivate
330{ return crd.seq(m_gridsize); }
size_t seq(const Coord &crd) const
Definition MarchingSquares.hpp:330

References m_gridsize, and marchsq::Coord::seq().

Referenced by streamdirs(), and streamtags().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ stepidx()

template<class Rst>
size_t marchsq::__impl::Grid< Rst >::stepidx ( const size_t idx,
const Dir d ) const
inlineprivate
334 {
336 switch (d) {
337 case Dir::left: return idx - 1;
338 case Dir::down: return idx + m_gridsize.c;
339 case Dir::right: return idx + 1;
340 case Dir::up: return idx - m_gridsize.c;
341 default: return idx;
342 }
343 }

References marchsq::__impl::down, marchsq::__impl::left, m_gridlen, m_gridsize, marchsq::__impl::right, and marchsq::__impl::up.

Referenced by scan_rings().

Here is the caller graph for this function:

◆ streamdirs()

template<class Rst>
std::ostream & marchsq::__impl::Grid< Rst >::streamdirs ( std::ostream & os)
inline
605 {
606 os << " :";
607 for (auto c = 0; c < m_gridsize.c; c++)
608 os << (c % 10);
609 os << "\n";
610 for (auto r = 0; r < m_gridsize.r; r++) {
611 os << std::setw(3) << r << ":";
612 for (auto c = 0; c < m_gridsize.c; c++)
613 os << get_dirs(seq(Coord(r, c)));
614 os << std::endl;
615 }
616 return os;
617 }

References get_dirs(), m_gridsize, and seq().

Here is the call graph for this function:

◆ streamtags()

template<class Rst>
std::ostream & marchsq::__impl::Grid< Rst >::streamtags ( std::ostream & os)
inline
590 {
591 os << " :";
592 for (auto c = 0; c < m_gridsize.c; c++)
593 os << (c % 10);
594 os << "\n";
595 for (auto r = 0; r < m_gridsize.r; r++) {
596 os << std::setw(3) << r << ":";
597 for (auto c = 0; c < m_gridsize.c; c++)
598 os << ((get_tags9(seq(Coord(r, c))) & 1) ? "H" : ".");
599 os << "\n";
600 }
601 return os;
602 }

References get_tags9(), m_gridsize, and seq().

Here is the call graph for this function:

◆ tag_grid()

template<class Rst>
template<class ExecutionPolicy>
void marchsq::__impl::Grid< Rst >::tag_grid ( ExecutionPolicy && policy,
TRasterValue< Rst > isoval )
inline
535 {
536 // Get all the tags. parallel?
538 [this, isoval](uint32_t& tag_block, size_t bidx) { tag_block = get_tags_block32(bidx, isoval); });
539 // streamtags(std::cerr);
540 // Get all the dirs. parallel?
542 [this](uint32_t& dirs_block, size_t bidx) { dirs_block = get_dirs_block8(bidx); });
543 // streamdirs(std::cerr);
544 }

References marchsq::__impl::for_each_idx(), marchsq::__impl::isoval(), m_dirs, and m_tags.

Here is the call graph for this function:

◆ tl()

template<class Rst>
Coord marchsq::__impl::Grid< Rst >::tl ( const Coord & crd) const
inlineprivate
242{ return rastercoord(crd); }

References rastercoord().

Referenced by _edge(), bl(), br(), and tr().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ tr()

template<class Rst>
Coord marchsq::__impl::Grid< Rst >::tr ( const Coord & crd) const
inlineprivate
241{ return tl(crd) + Coord{0, m_window.c}; }

References m_window, and tl().

Referenced by _edge().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ m_dirs

template<class Rst>
std::vector<uint32_t> marchsq::__impl::Grid< Rst >::m_dirs
private

◆ m_gridlen

template<class Rst>
size_t marchsq::__impl::Grid< Rst >::m_gridlen
private

◆ m_gridsize

template<class Rst>
Coord marchsq::__impl::Grid< Rst >::m_gridsize
private

◆ m_rastsize

template<class Rst>
Coord marchsq::__impl::Grid< Rst >::m_rastsize
private

Referenced by Grid(), edge(), and is_within().

◆ m_rst

template<class Rst>
const Rst* marchsq::__impl::Grid< Rst >::m_rst = nullptr
private

Referenced by Grid(), _edge(), and get_tags_block32().

◆ m_tags

template<class Rst>
std::vector<uint32_t> marchsq::__impl::Grid< Rst >::m_tags
private

Referenced by Grid(), get_tags9(), and tag_grid().

◆ m_window

template<class Rst>
Coord marchsq::__impl::Grid< Rst >::m_window
private

The documentation for this class was generated from the following file: