ExPolygonsIndex.cpp 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. #include "ExPolygonsIndex.hpp"
  2. using namespace Slic3r;
  3. // IMPROVE: use one dimensional vector for polygons offset with searching by std::lower_bound
  4. ExPolygonsIndices::ExPolygonsIndices(const ExPolygons &shapes)
  5. {
  6. // prepare offsets
  7. m_offsets.reserve(shapes.size());
  8. uint32_t offset = 0;
  9. for (const ExPolygon &shape : shapes) {
  10. assert(!shape.contour.points.empty());
  11. std::vector<uint32_t> shape_offsets;
  12. shape_offsets.reserve(shape.holes.size() + 1);
  13. shape_offsets.push_back(offset);
  14. offset += shape.contour.points.size();
  15. for (const Polygon &hole: shape.holes) {
  16. shape_offsets.push_back(offset);
  17. offset += hole.points.size();
  18. }
  19. m_offsets.push_back(std::move(shape_offsets));
  20. }
  21. m_count = offset;
  22. }
  23. uint32_t ExPolygonsIndices::cvt(const ExPolygonsIndex &id) const
  24. {
  25. assert(id.expolygons_index < m_offsets.size());
  26. const std::vector<uint32_t> &shape_offset = m_offsets[id.expolygons_index];
  27. assert(id.polygon_index < shape_offset.size());
  28. uint32_t res = shape_offset[id.polygon_index] + id.point_index;
  29. assert(res < m_count);
  30. return res;
  31. }
  32. ExPolygonsIndex ExPolygonsIndices::cvt(uint32_t index) const
  33. {
  34. assert(index < m_count);
  35. ExPolygonsIndex result{0, 0, 0};
  36. // find expolygon index
  37. auto fn = [](const std::vector<uint32_t> &offsets, uint32_t index) { return offsets[0] < index; };
  38. auto it = std::lower_bound(m_offsets.begin() + 1, m_offsets.end(), index, fn);
  39. result.expolygons_index = it - m_offsets.begin();
  40. if (it == m_offsets.end() || it->at(0) != index) --result.expolygons_index;
  41. // find polygon index
  42. const std::vector<uint32_t> &shape_offset = m_offsets[result.expolygons_index];
  43. auto it2 = std::lower_bound(shape_offset.begin() + 1, shape_offset.end(), index);
  44. result.polygon_index = it2 - shape_offset.begin();
  45. if (it2 == shape_offset.end() || *it2 != index) --result.polygon_index;
  46. // calculate point index
  47. uint32_t polygon_offset = shape_offset[result.polygon_index];
  48. assert(index >= polygon_offset);
  49. result.point_index = index - polygon_offset;
  50. return result;
  51. }
  52. bool ExPolygonsIndices::is_last_point(const ExPolygonsIndex &id) const {
  53. assert(id.expolygons_index < m_offsets.size());
  54. const std::vector<uint32_t> &shape_offset = m_offsets[id.expolygons_index];
  55. assert(id.polygon_index < shape_offset.size());
  56. uint32_t index = shape_offset[id.polygon_index] + id.point_index;
  57. assert(index < m_count);
  58. // next index
  59. uint32_t next_point_index = index + 1;
  60. uint32_t next_poly_index = id.polygon_index + 1;
  61. uint32_t next_expoly_index = id.expolygons_index + 1;
  62. // is last expoly?
  63. if (next_expoly_index == m_offsets.size()) {
  64. // is last expoly last poly?
  65. if (next_poly_index == shape_offset.size())
  66. return next_point_index == m_count;
  67. } else {
  68. // (not last expoly) is expoly last poly?
  69. if (next_poly_index == shape_offset.size())
  70. return next_point_index == m_offsets[next_expoly_index][0];
  71. }
  72. // Not last polygon in expolygon
  73. return next_point_index == shape_offset[next_poly_index];
  74. }
  75. uint32_t ExPolygonsIndices::get_count() const { return m_count; }