mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 20:51:12 -06:00 
			
		
		
		
	utility class ClosestPointInRadiusLookup
This commit is contained in:
		
							parent
							
								
									c5843988c0
								
							
						
					
					
						commit
						1699864b8a
					
				
					 1 changed files with 96 additions and 1 deletions
				
			
		|  | @ -6,6 +6,7 @@ | |||
| #include <math.h> | ||||
| #include <string> | ||||
| #include <sstream> | ||||
| #include <unordered_map> | ||||
| 
 | ||||
| namespace Slic3r { | ||||
| 
 | ||||
|  | @ -71,12 +72,105 @@ inline Point operator+(const Point& point1, const Point& point2) { return Point( | |||
| inline Point operator-(const Point& point1, const Point& point2) { return Point(point1.x - point2.x, point1.y - point2.y); } | ||||
| inline Point operator*(double scalar, const Point& point2) { return Point(scalar * point2.x, scalar * point2.y); } | ||||
| 
 | ||||
| // To be used by std::unordered_map, std::unordered_multimap and friends.
 | ||||
| struct PointHash { | ||||
|     size_t operator()(const Point &pt) const { | ||||
|         return std::hash<coord_t>()(pt.x) ^ std::hash<coord_t>()(pt.y); | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| // A generic class to search for a closest Point in a given radius.
 | ||||
| // It uses std::unordered_multimap to implement an efficient 2D spatial hashing.
 | ||||
| // The PointAccessor has to return const Point*.
 | ||||
| // If a nullptr is returned, it is ignored by the query.
 | ||||
| template<typename ValueType, typename PointAccessor> class ClosestPointInRadiusLookup | ||||
| { | ||||
| public: | ||||
|     ClosestPointInRadiusLookup(coord_t search_radius, PointAccessor point_accessor = PointAccessor()) :  | ||||
| 		m_search_radius(search_radius), m_point_accessor(point_accessor), m_grid_log2(0) | ||||
|     { | ||||
|         // Resolution of a grid, twice the search radius + some epsilon.
 | ||||
| 		coord_t gridres = 2 * m_search_radius + 4; | ||||
|         m_grid_resolution = gridres; | ||||
|         assert(m_grid_resolution > 0); | ||||
|         assert(m_grid_resolution < (coord_t(1) << 30)); | ||||
| 		// Compute m_grid_log2 = log2(m_grid_resolution)
 | ||||
| 		if (m_grid_resolution > 32767) { | ||||
| 			m_grid_resolution >>= 16; | ||||
| 			m_grid_log2 += 16; | ||||
| 		} | ||||
| 		if (m_grid_resolution > 127) { | ||||
| 			m_grid_resolution >>= 8; | ||||
| 			m_grid_log2 += 8; | ||||
| 		} | ||||
| 		if (m_grid_resolution > 7) { | ||||
| 			m_grid_resolution >>= 4; | ||||
| 			m_grid_log2 += 4; | ||||
| 		} | ||||
| 		if (m_grid_resolution > 1) { | ||||
| 			m_grid_resolution >>= 2; | ||||
| 			m_grid_log2 += 2; | ||||
| 		} | ||||
| 		if (m_grid_resolution > 0) | ||||
| 			++ m_grid_log2; | ||||
| 		m_grid_resolution = 1 << m_grid_log2; | ||||
| 		assert(m_grid_resolution >= gridres); | ||||
| 		assert(gridres > m_grid_resolution / 2); | ||||
|     } | ||||
| 
 | ||||
|     void insert(const ValueType &value) { | ||||
|         const Point *pt = m_point_accessor(value); | ||||
|         if (pt != nullptr) | ||||
|             m_map.emplace(std::make_pair(Point(pt->x>>m_grid_log2, pt->y>>m_grid_log2), value)); | ||||
|     } | ||||
| 
 | ||||
|     void insert(ValueType &&value) { | ||||
|         const Point *pt = m_point_accessor(value); | ||||
|         if (pt != nullptr) | ||||
|             m_map.emplace(std::make_pair(Point(pt->x>>m_grid_log2, pt->y>>m_grid_log2), std::move(value))); | ||||
|     } | ||||
| 
 | ||||
|     // Return a pair of <ValueType*, distance_squared>
 | ||||
|     std::pair<const ValueType*, double> find(const Point &pt) { | ||||
|         // Iterate over 4 closest grid cells around pt,
 | ||||
|         // find the closest start point inside these cells to pt.
 | ||||
|         const ValueType *value_min = nullptr; | ||||
|         double           dist_min = std::numeric_limits<double>::max(); | ||||
|         // Round pt to a closest grid_cell corner.
 | ||||
|         Point            grid_corner((pt.x+(m_grid_resolution>>1))>>m_grid_log2, (pt.y+(m_grid_resolution>>1))>>m_grid_log2); | ||||
|         // For four neighbors of grid_corner:
 | ||||
|         for (coord_t neighbor_y = -1; neighbor_y < 1; ++ neighbor_y) { | ||||
|             for (coord_t neighbor_x = -1; neighbor_x < 1; ++ neighbor_x) { | ||||
|                 // Range of fragment starts around grid_corner, close to pt.
 | ||||
|                 auto range = m_map.equal_range(Point(grid_corner.x + neighbor_x, grid_corner.y + neighbor_y)); | ||||
|                 // Find the map entry closest to pt.
 | ||||
|                 for (auto it = range.first; it != range.second; ++it) { | ||||
|                     const ValueType &value = it->second; | ||||
|                     const Point *pt2 = m_point_accessor(value); | ||||
|                     if (pt2 != nullptr) { | ||||
|                         const double d2 = pt.distance_to_sq(*pt2); | ||||
|                         if (d2 < dist_min) { | ||||
|                             dist_min = d2; | ||||
|                             value_min = &value; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return (value_min != nullptr && dist_min < coordf_t(m_search_radius * m_search_radius)) ?  | ||||
|             std::make_pair(value_min, dist_min) :  | ||||
|             std::make_pair(nullptr, std::numeric_limits<double>::max()); | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     typedef typename std::unordered_multimap<Point, ValueType, PointHash> map_type; | ||||
|     PointAccessor m_point_accessor; | ||||
|     map_type m_map; | ||||
|     coord_t  m_search_radius; | ||||
|     coord_t  m_grid_resolution; | ||||
|     coord_t  m_grid_log2; | ||||
| }; | ||||
| 
 | ||||
| class Point3 : public Point | ||||
| { | ||||
|     public: | ||||
|  | @ -114,7 +208,8 @@ inline Pointf operator-(const Pointf& point1, const Pointf& point2) { return Poi | |||
| inline Pointf operator*(double scalar, const Pointf& point2) { return Pointf(scalar * point2.x, scalar * point2.y); } | ||||
| inline Pointf operator*(const Pointf& point2, double scalar) { return Pointf(scalar * point2.x, scalar * point2.y); } | ||||
| inline coordf_t cross(const Pointf &v1, const Pointf &v2) { return v1.x * v2.y - v1.y * v2.x; } | ||||
| inline coordf_t dot(const Pointf &v1, const Pointf &v2) { return v1.x * v1.y + v2.x * v2.y; } | ||||
| inline coordf_t dot(const Pointf &v1, const Pointf &v2) { return v1.x * v2.x + v1.y * v2.y; } | ||||
| inline coordf_t dot(const Pointf &v) { return v.x * v.x + v.y * v.y; } | ||||
| 
 | ||||
| class Pointf3 : public Pointf | ||||
| { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 bubnikv
						bubnikv