static std::vector<NearestPhoton>::iterator nearest(std::vector<Photon>::const_iterator begin, std::vector<Photon>::const_iterator end, Segment3f const& bound, Point3f const& position, std::vector<NearestPhoton>::iterator nearestBegin, std::vector<NearestPhoton>::iterator nearestNext, std::vector<NearestPhoton>::iterator nearestEnd) { if (begin == end) { return nearestNext; } std::vector<Photon>::const_iterator median = begin + (end - begin) / 2; float medianSqrDistance = sqrDistance(median->position, position); if (nearestNext == nearestEnd) { if (medianSqrDistance < nearestBegin->sqrDistance) { std::pop_heap(nearestBegin, nearestNext--, SqrDistanceLess()); nearestNext->photon = median; nearestNext->sqrDistance = medianSqrDistance; std::push_heap(nearestBegin, ++nearestNext, SqrDistanceLess()); } } else { nearestNext->photon = median; nearestNext->sqrDistance = medianSqrDistance; std::push_heap(nearestBegin, ++nearestNext, SqrDistanceLess()); } int splitAxis = maxAxis(bound); if (position[splitAxis] <= median->position[splitAxis]) { Segment3f belowBound = bound; belowBound.max[splitAxis] = median->position[splitAxis]; nearestNext = nearest(begin, median, belowBound, position, nearestBegin, nearestNext, nearestEnd); } else { Segment3f aboveBound = bound; aboveBound.min[splitAxis] = median->position[splitAxis]; nearestNext = nearest(median + 1, end, aboveBound, position, nearestBegin, nearestNext, nearestEnd); } if (nearestNext != nearestEnd || sqr(median->position[splitAxis] - position[splitAxis]) < nearestBegin->sqrDistance) { if (position[splitAxis] <= median->position[splitAxis]) { Segment3f aboveBound = bound; aboveBound.min[splitAxis] = median->position[splitAxis]; nearestNext = nearest(median + 1, end, aboveBound, position, nearestBegin, nearestNext, nearestEnd); } else { Segment3f belowBound = bound; belowBound.max[splitAxis] = median->position[splitAxis]; nearestNext = nearest(begin, median, belowBound, position, nearestBegin, nearestNext, nearestEnd); } } return nearestNext; }
void buildLevelOnSubtree(int level, int subtree, std::vector<Photon>::iterator begin, std::vector<Photon>::iterator end, Segment3f const& bound) { if (begin == end) { return; } int splitAxis = maxAxis(bound); if (level == 0) { std::sort(begin, end, [=](Photon const& a, Photon const& b) { return a.position[splitAxis] < b.position[splitAxis]; }); return; } std::vector<Photon>::iterator median = begin + (end - begin) / 2; int mask = 1 << (level - 1); if ((subtree & mask) == 0) { Segment3f belowBound = bound; belowBound.max[splitAxis] = median->position[splitAxis]; buildLevelOnSubtree(level - 1, subtree & ~mask, begin, median, belowBound); } else { Segment3f aboveBound = bound; aboveBound.min[splitAxis] = median->position[splitAxis]; buildLevelOnSubtree(level - 1, subtree & ~mask, median + 1, end, aboveBound); } }
/** * Get the maximum component in the vector (according to signed comparison). To compare absolute values, use maxAbs() * instead. */ T const & max() const { return values[maxAxis()]; }
int maxAxis(Segment3<T> const& segment) { return maxAxis(extent(segment)); }