|
30 | 30 | using Vec2 = glm::dvec2; |
31 | 31 | using Vec3 = glm::dvec3; |
32 | 32 |
|
| 33 | + |
| 34 | +// Custom hash for std::tuple<int64_t, int64_t, int64_t> |
| 35 | +// Combine the three 64-bit integers in a reasonably collision-resistant way |
| 36 | +template<> |
| 37 | +struct std::hash<std::tuple<int64_t, int64_t, int64_t>> |
| 38 | +{ |
| 39 | + using argument_type = std::tuple<int64_t, int64_t, int64_t>; |
| 40 | + using result_type = std::size_t; |
| 41 | + |
| 42 | + result_type operator()(const argument_type& t) const noexcept |
| 43 | + { |
| 44 | + auto [x, y, z] = t; // C++17 structured binding (preferred) |
| 45 | + |
| 46 | + // Simple, fast mixing - inspired by boost::hash_combine + murmur-like finalizer |
| 47 | + std::size_t seed = 0x517cc1b727220a95ULL; // random 64-bit constant |
| 48 | + |
| 49 | + seed ^= static_cast<std::size_t>(x) + 0x9e3779b97f4a7c15ULL + (seed << 6) + (seed >> 2); |
| 50 | + seed ^= static_cast<std::size_t>(y) + 0x9e3779b97f4a7c15ULL + (seed << 6) + (seed >> 2); |
| 51 | + seed ^= static_cast<std::size_t>(z) + 0x9e3779b97f4a7c15ULL + (seed << 6) + (seed >> 2); |
| 52 | + |
| 53 | + return seed; |
| 54 | + } |
| 55 | +}; |
| 56 | + |
33 | 57 | namespace fuzzybools |
34 | 58 | { |
35 | 59 |
|
@@ -680,6 +704,8 @@ namespace fuzzybools |
680 | 704 | BVH relevantBVHA; |
681 | 705 | BVH relevantBVHB; |
682 | 706 |
|
| 707 | + std::unordered_map<std::tuple<int64_t, int64_t, int64_t>, std::vector<size_t>> pointGrid; |
| 708 | + |
683 | 709 | //============================================================================================ |
684 | 710 |
|
685 | 711 | // assumes all triangleIds are connected to base with an edge and are flipped correctly |
@@ -839,23 +865,53 @@ namespace fuzzybools |
839 | 865 | } |
840 | 866 |
|
841 | 867 | //============================================================================================ |
842 | | - |
843 | | - size_t AddPoint(const Vec3 &newPoint) |
844 | | - { |
845 | | - for (auto &pt : points) |
846 | | - { |
847 | | - if (pt == newPoint) |
848 | | - { |
849 | | - return pt.id; |
| 868 | + size_t AddPoint(const Vec3& newPoint) |
| 869 | + { |
| 870 | + // 1. Compute the grid cell for the query point |
| 871 | + const double cellSize = toleranceVectorEquality; // same tolerance you already use for == |
| 872 | + |
| 873 | + auto getKey = [&](const Vec3& p) -> std::tuple<int64_t, int64_t, int64_t> { |
| 874 | + return { |
| 875 | + static_cast<int64_t>(std::floor(p.x / cellSize)), |
| 876 | + static_cast<int64_t>(std::floor(p.y / cellSize)), |
| 877 | + static_cast<int64_t>(std::floor(p.z / cellSize)) |
| 878 | + }; |
| 879 | + }; |
| 880 | + |
| 881 | + const auto centerKey = getKey(newPoint); |
| 882 | + |
| 883 | + // 2. Check the point against all 27 neighbouring cells (guaranteed to contain any point |
| 884 | + // that is within toleranceVectorEquality because |delta_x|,|delta_y|,|delta_z| < tolerance) |
| 885 | + for (int dx = -1; dx <= 1; ++dx) { |
| 886 | + for (int dy = -1; dy <= 1; ++dy) { |
| 887 | + for (int dz = -1; dz <= 1; ++dz) { |
| 888 | + const std::tuple<int64_t, int64_t, int64_t> neighbourKey = { |
| 889 | + std::get<0>(centerKey) + dx, |
| 890 | + std::get<1>(centerKey) + dy, |
| 891 | + std::get<2>(centerKey) + dz |
| 892 | + }; |
| 893 | + |
| 894 | + auto it = pointGrid.find(neighbourKey); |
| 895 | + if (it != pointGrid.end()) { |
| 896 | + for (size_t existingId : it->second) { |
| 897 | + if (points[existingId] == newPoint) { // re-uses your existing tolerance check |
| 898 | + return existingId; |
| 899 | + } |
| 900 | + } |
| 901 | + } |
| 902 | + } |
850 | 903 | } |
851 | 904 | } |
852 | 905 |
|
| 906 | + // 3. Point does not exist -> insert it |
853 | 907 | Point p; |
854 | 908 | p.id = points.size(); |
855 | 909 | p.location3D = newPoint; |
856 | | - |
857 | 910 | points.push_back(p); |
858 | 911 |
|
| 912 | + // Insert into spatial grid (same cell as the point itself) |
| 913 | + pointGrid[getKey(newPoint)].push_back(p.id); |
| 914 | + |
859 | 915 | return p.id; |
860 | 916 | } |
861 | 917 |
|
|
0 commit comments