CGI/exercise3/include/HashGrid.h
2018-09-06 14:35:43 +02:00

264 lines
7.2 KiB
C++

// This source code is property of the Computer Graphics and Visualization
// chair of the TU Dresden. Do not distribute!
// Copyright (C) CGV TU Dresden - All Rights Reserved
#pragma once
#include <unordered_map>
#include <array>
#include <vector>
#include "Box.h"
#include "GridUtils.h"
#include "Triangle.h"
#include "Point.h"
#include "LineSegment.h"
template <typename Primitive >
class HashGrid
{
public:
//hash function
struct GridHashFunc
{
size_t operator()(const Eigen::Vector3i &idx ) const
{
static const int p1 = 131071;
static const int p2 = 524287;
static const int p3 = 8191;
return idx[0] * p1 + idx[1] * p2 + idx[2] * p3;
}
};
//type of internal hash map
typedef std::unordered_map<Eigen::Vector3i,std::vector<Primitive>,GridHashFunc> CellHashMapType;
private:
//internal hash map storing the data of each non empty grid cell
//it is a map with a 3 dimensional cell index index as a key and a std::vector<Primitive> as value type
CellHashMapType cellHashMap;
//internal extents of a cell
Eigen::Vector3f cellExtents;
public:
//constructor for hash grid with uniform cell extent
//initial size is used to preallocate memory for the internal unordered map
HashGrid(const float cellExtent=0.01,const int initialSize=1): cellHashMap(initialSize)
{
cellExtents[0] =cellExtents[1] =cellExtents[2] = cellExtent;
}
//constructor for hash grid with non uniform cell extents
//initial size is used to preallocate memory for the internal unordered map
HashGrid(const Eigen::Vector3f& cellExtents,const int initialSize): cellHashMap(initialSize),cellExtents(cellExtents)
{
}
//resize hash map with at least count buckets
void ReHash(const int count)
{
cellHashMap.rehash(count);
}
//converts a position to a grid index
Eigen::Vector3i PositionToIndex(const Eigen::Vector3f& pos) const
{
return PositionToCellIndex(pos, cellExtents) ;
}
//return the center position of a cell specified by its cell key
Eigen::Vector3f CellCenter(const Eigen::Vector3i& idx) const
{
Eigen::Vector3f p;
for(int d = 0; d < 3; ++d)
p[d] = (idx[d] + 0.5f)*cellExtents[d];
return p;
}
//return the center position of a cell containing give position pos
Eigen::Vector3f CellCenter(const Eigen::Vector3f& pos) const
{
return CellCenter(PositionToIndex(pos));
}
//return the min corner position of a cell specified by its cell key
Eigen::Vector3f CellMinPosition(const Eigen::Vector3i& key) const
{
Eigen::Vector3f p;
for(int d = 0; d < 3; ++d)
p[d] = key[d]*cellExtents[d];
return p;
}
//return the min corner position of a cell containing the point pos
Eigen::Vector3f CellMinPosition(const Eigen::Vector3f& pos) const
{
return CellMinPosition(PositionToIndex(pos));
}
//return the max corner position of a cell specified by its cell key
Eigen::Vector3f CellMaxPosition(const Eigen::Vector3i& idx) const
{
Eigen::Vector3f p;
for(int d = 0; d < 3; ++d)
p[d] = (idx[d]+1)*cellExtents[d];
return p;
}
//return the max corner position of a cell containing the point pos
Eigen::Vector3f CellMaxPosition(const Eigen::Vector3f& pos) const
{
return CellMaxPosition(PositionToIndex(pos));
}
//returns bounding box of cell with index idx
Box CellBounds(const Eigen::Vector3i& idx) const
{
return Box(CellMinPosition(idx),CellMaxPosition(idx));
}
//returns the bounding box of cell containing the point pos
Box CellBounds(const Eigen::Vector3f& pos) const
{
Eigen::Vector3i idx = PositionToIndex(pos);
return Box(CellMinPosition(idx),CellMaxPosition(idx));
}
//returns the extents of a grid cell
Eigen::Vector3f CellExtents() const
{
return cellExtents;
}
//returns volume of a grid cell
float CellVolume() const
{
float vol = 0;
for(int d = 0; d < 3; ++d)
vol *= cellExtents[d];
return vol;
}
//removes all non empty cells from the hash grid
bool Empty(const Eigen::Vector3i& idx) const
{
auto it = cellHashMap.find(idx);
if(it == cellHashMap.end())
return true;
return false;
}
//inserts primitive p into all overlapping hash grid cells
//the primitive must implement a method "box compute_bounds()" which returns an axis aligned bounding box
//and a method "bool overlaps(const box& b)" which returns true if the primitive overlaps the given box b
void Insert(const Primitive& p)
{
Box b = p.ComputeBounds();
Eigen::Vector3f lb = b.LowerBound();
Eigen::Vector3f ub = b.UpperBound();
if(lb[0] > ub[0])
return;
if(lb[1] > ub[1])
return;
if(lb[2] > ub[2])
return;
Eigen::Vector3i lb_idx = PositionToIndex(lb);
Eigen::Vector3i ub_idx = PositionToIndex(ub);
Eigen::Vector3i idx;
for(idx[0] = lb_idx[0]; idx[0] <=ub_idx[0]; ++idx[0])
for(idx[1] = lb_idx[1]; idx[1] <=ub_idx[1]; ++idx[1])
for(idx[2] = lb_idx[2]; idx[2] <=ub_idx[2]; ++idx[2])
if(p.Overlaps(CellBounds(idx)))
cellHashMap[idx].push_back(p);
}
//remove all cells from hash grid
void Clear()
{
cellHashMap.clear();
}
//returns true if hashgrid contains no cells
bool Empty() const
{
return cellHashMap.empty();
}
//returns the number of non empty cells
size_t NumCells() const
{
return cellHashMap.size();
}
//iterator pointing to the first cell within the hashgrid
typename CellHashMapType::iterator NonEmptyCellsBegin()
{
return cellHashMap.begin();
}
//iterator pointing behind the last cell within the hashgrid
typename CellHashMapType::iterator NonEmptyCellsEnd()
{
return cellHashMap.end();
}
//const iterator pointing to the first cell within the hashgrid
typename CellHashMapType::const_iterator NonEmptyCellsBegin() const
{
return cellHashMap.begin();
}
//const iterator pointing behind the last cell within the hashgrid
typename CellHashMapType::const_iterator NonEmptyCellsEnd() const
{
return cellHashMap.end();
}
//iterator pointing to the first primitive stored in the cell idx
typename std::vector<Primitive>::iterator PrimitivesBegin(const Eigen::Vector3i& idx)
{
assert(!Empty(idx));
return cellHashMap[idx].begin();
}
//iterator pointing after the last primitive stored in the cell idx
typename std::vector<Primitive>::iterator PrimitivesEnd(const Eigen::Vector3i& idx)
{
assert(!Empty(idx));
return cellHashMap[idx].end();
}
//const iterator pointing to the first primitive stored in the cell idx
typename std::vector<Primitive>::const_iterator PrimitivesBegin(const Eigen::Vector3i& idx) const
{
assert(!Empty(idx));
return cellHashMap[idx].cbegin();
}
//const iterator pointing after the last primitive stored in the cell idx
typename std::vector<Primitive>::const_iterator PrimitivesEnd(const Eigen::Vector3i& idx) const
{
assert(!Empty(idx));
return cellHashMap[idx].cend();
}
};
//helper function to construct a hashgrid data structure from the triangle faces of the halfedge mesh m
void BuildHashGridFromTriangles(const HEMesh& m, HashGrid<Triangle>& grid, const Eigen::Vector3f& cellSize);
//helper function to construct a hashgrid data structure from the vertices of the halfedge mesh m
void BuildHashGridFromVertices(const HEMesh& m, HashGrid<Point>& grid, const Eigen::Vector3f& cellSize);
//helper function to construct a hashgrid data structure from the edges of the halfedge mesh m
void BuildHashGridFromEdges(const HEMesh& m, HashGrid<LineSegment >& grid, const Eigen::Vector3f& cellSize);