From f189954598b8872e97176b396dd8abb399baa1e8 Mon Sep 17 00:00:00 2001
From: Thomas Fischer <thomas.fischer@ufz.de>
Date: Tue, 22 May 2012 14:52:56 +0200
Subject: [PATCH] forgot to add the files into the previous commit

---
 GeoLib/Grid.h    | 465 +++++++++++++++++++++++++++++++++++++++++++++++
 GeoLib/OctTree.h | 241 ++++++++++++++++++++++++
 2 files changed, 706 insertions(+)
 create mode 100644 GeoLib/Grid.h
 create mode 100644 GeoLib/OctTree.h

diff --git a/GeoLib/Grid.h b/GeoLib/Grid.h
new file mode 100644
index 00000000000..b799c9e4ebd
--- /dev/null
+++ b/GeoLib/Grid.h
@@ -0,0 +1,465 @@
+/*
+ * Grid.h
+ *
+ *  Created on: Feb 2, 2012
+ *      Author: TF
+ */
+
+#ifndef GRID_H_
+#define GRID_H_
+
+#include <vector>
+
+// GeoLib
+#include "AxisAlignedBoundingBox.h"
+
+#ifndef NDEBUG
+// BaseLib
+#include "StringTools.h"
+#endif
+
+namespace GeoLib {
+
+template <typename POINT>
+class Grid : public GeoLib::AABB
+{
+public:
+	/**
+	 * @brief The constructor of the grid object takes a vector of points. Furthermore the
+	 * use can specify the maximum number of points per grid cell (in the average!).
+	 *
+	 * The number of grid cells are computed with the following formula
+	 * \f$\frac{n_{points}}{n_{cells}} \le n_{max\_per\_cell}\f$
+	 *
+	 * In order to limit the memory wasting the maximum number of points per grid cell
+	 * (in the average) should be a power of two.
+	 *
+	 * @param pnts (input) the points that are managed with the Grid
+	 * @param max_num_per_grid_cell (input) max number per grid cell in the average (default 512)
+	 */
+	Grid(std::vector<POINT*> const& pnts, size_t max_num_per_grid_cell = 512);
+
+	/**
+	 * This is the destructor of the class. It deletes the internal data structures *not*
+	 * including the pointers to the points.
+	 */
+	virtual ~Grid()
+	{
+		delete [] _grid_quad_to_node_map;
+	}
+
+	/**
+	 * The method calculates the grid cell within the grid to given point is belonging to, i.e.,
+	 * the (internal) coordinates of the grid are computed. The method searches the actual
+	 * grid cell and all its possible neighbors for the POINT object which has the smallest
+	 * distance. A pointer to this object is returned.
+	 *
+	 * If there is not such a point, i.e., all the searched grid cells do not contain any
+	 * POINT object a NULL pointer is returned.
+	 *
+	 * @param pnt a field that holds the coordinates of the point
+	 * @return a point with the smallest distance within the grid cells that are outlined above or NULL
+	 */
+	POINT const* getNearestPoint(double const*const pnt) const;
+
+	/**
+	 * Method fetchs all points that are located within grid cells that intersects
+	 * the axis aligned cube defined by its center and half edge length.
+	 *
+	 * @param pnt (input) the center point of the axis aligned cube
+	 * @param half_len (input) half of the edge length of the axis aligned cube
+	 * @param pnts (output) all points within grid cells that intersects
+	 * the axis aligned cube
+	 */
+	void getPointsWithinCube(double const*const pnt, double half_len, std::vector<POINT*>& pnts) const;
+
+#ifndef NDEBUG
+	/**
+	 * Method creates a geometry for every mesh grid box. Additionally it
+	 * creates one geometry containing all the box geometries.
+	 * @param geo_obj
+	 */
+	void createGridGeometry(GeoLib::GEOObjects* geo_obj) const;
+#endif
+
+private:
+	/**
+	 * Method calculates the grid cell coordinates for the given point pnt. If
+	 * the point is located outside of the bounding box the coordinates of the
+	 * grid cell on the border that is nearest to given point will be returned.
+	 * @param pnt (input) the coordinates of the point
+	 * @param coords (output) the coordinates of the grid cell
+	 */
+	inline void getGridCoords(double const*const pnt, size_t* coords) const;
+
+	/**
+	 *
+	 * point numbering of the grid cell is as follow
+	 *	     7 -------- 6
+	 *	    /:         /|
+	 *	   / :        / |
+	 *	  /  :       /  |
+	 *	 /   :      /   |
+	 *  4 -------- 5    |
+	 *	|    3 ....|... 2
+	 *	|   .      |   /
+	 *	|  .       |  /
+	 *	| .        | /
+	 *	|.         |/
+	 *	0 -------- 1
+	 *	the face numbering is as follow:
+	 *	face	nodes
+	 *	0		0,3,2,1 bottom
+	 *	1		0,1,5,4 front
+	 *	2		1,2,6,5 right
+	 *	3		2,3,7,6 back
+	 *	4		3,0,4,7 left
+	 *	5		4,5,6,7 top
+	 * @param pnt (input) coordinates of the point
+	 * @param sqr_dists (output) squared distances of the point to the faces
+	 * ordered in the same sequence as above described
+	 * @param coords coordinates of the grid cell
+	 */
+	void getPointCellBorderDistances(double const*const pnt, double dists[6], size_t const* const coords) const;
+
+	bool calcNearestPointInGridCell(double const* const pnt, size_t const* const coords,
+					double &sqr_min_dist, POINT* &nearest_pnt) const;
+	double _step_sizes[3];
+	double _inverse_step_sizes[3];
+	size_t _n_steps[3];
+	std::vector<POINT*>* _grid_quad_to_node_map;
+};
+
+
+template <typename POINT>
+Grid<POINT>::Grid(std::vector<POINT*> const& pnts, size_t max_num_per_grid_cell) :
+	GeoLib::AABB(), _grid_quad_to_node_map(NULL)
+{
+	// compute axis aligned bounding box
+	const size_t n_pnts(pnts.size());
+	for (size_t k(0); k < n_pnts; k++) {
+		this->update(pnts[k]->getCoords());
+	}
+
+	double delta[3] = { 0.0, 0.0, 0.0 };
+	for (size_t k(0); k < 3; k++) {
+		// make the bounding box a little bit bigger,
+		// such that the node with maximal coordinates fits into the grid
+		_max_pnt[k] *= (1.0 + 1e-6);
+		if (fabs(_max_pnt[k]) < std::numeric_limits<double>::epsilon()) {
+			_max_pnt[k] = (_max_pnt[k] - _min_pnt[k]) * (1.0 + 1e-6);
+		}
+		delta[k] = _max_pnt[k] - _min_pnt[k];
+	}
+
+	// *** condition: n_pnts / (_n_steps[0] * _n_steps[1] * _n_steps[2]) < max_num_per_grid_cell
+	// *** with _n_steps[1] = _n_steps[0] * delta[1]/delta[0], _n_steps[2] = _n_steps[0] * delta[2]/delta[0]
+	if (fabs(delta[1]) < std::numeric_limits<double>::epsilon() ||
+					fabs(delta[2]) < std::numeric_limits<double>::epsilon()) {
+		// 1d case y = z = 0
+		if (fabs(delta[1]) < std::numeric_limits<double>::epsilon() &&
+						fabs(delta[2]) < std::numeric_limits<double>::epsilon()) {
+			_n_steps[0] = static_cast<size_t> (ceil(n_pnts / (double) max_num_per_grid_cell));
+			_n_steps[1] = 1;
+			_n_steps[2] = 1;
+		} else {
+			// 1d case x = z = 0
+			if (fabs(delta[0]) < std::numeric_limits<double>::epsilon() &&
+							fabs(delta[2]) < std::numeric_limits<double>::epsilon()) {
+				_n_steps[0] = 1;
+				_n_steps[1] = static_cast<size_t> (ceil(n_pnts / (double) max_num_per_grid_cell));
+				_n_steps[2] = 1;
+			} else {
+				// 1d case x = y = 0
+				if (fabs(delta[0]) < std::numeric_limits<double>::epsilon() && fabs(delta[1])
+								< std::numeric_limits<double>::epsilon()) {
+					_n_steps[0] = 1;
+					_n_steps[1] = 1;
+					_n_steps[2] = static_cast<size_t> (ceil(n_pnts / (double) max_num_per_grid_cell));
+				} else {
+					// 2d case
+					if (fabs(delta[1]) < std::numeric_limits<double>::epsilon()) {
+						_n_steps[0] = static_cast<size_t> (ceil(sqrt(n_pnts * delta[0] / (max_num_per_grid_cell * delta[2]))));
+						_n_steps[1] = 1;
+						_n_steps[2] = static_cast<size_t> (ceil(_n_steps[0] * delta[2] / delta[0]));
+					} else {
+						_n_steps[0] = static_cast<size_t> (ceil(sqrt(n_pnts * delta[0] / (max_num_per_grid_cell * delta[1]))));
+						_n_steps[1] = static_cast<size_t> (ceil(_n_steps[0] * delta[1] / delta[0]));
+						_n_steps[2] = 1;
+					}
+				}
+			}
+		}
+	} else {
+		// 3d case
+		_n_steps[0] = static_cast<size_t> (ceil(pow(n_pnts * delta[0] * delta[0]
+						/ (max_num_per_grid_cell * delta[1] * delta[2]), 1. / 3.)));
+		_n_steps[1] = static_cast<size_t> (ceil(_n_steps[0] * delta[1] / delta[0]));
+		_n_steps[2] = static_cast<size_t> (ceil(_n_steps[0] * delta[2] / delta[0]));
+	}
+
+	const size_t n_plane(_n_steps[0] * _n_steps[1]);
+	_grid_quad_to_node_map = new std::vector<POINT*>[n_plane * _n_steps[2]];
+
+	// some frequently used expressions to fill the grid vectors
+	for (size_t k(0); k < 3; k++) {
+		_step_sizes[k] = delta[k] / _n_steps[k];
+		_inverse_step_sizes[k] = 1.0 / _step_sizes[k];
+	}
+
+	// fill the grid vectors
+	for (size_t l(0); l < n_pnts; l++) {
+		double const* const pnt(pnts[l]->getCoords());
+		const size_t i(static_cast<size_t> ((pnt[0] - _min_pnt[0]) * _inverse_step_sizes[0]));
+		const size_t j(static_cast<size_t> ((pnt[1] - _min_pnt[1]) * _inverse_step_sizes[1]));
+		const size_t k(static_cast<size_t> ((pnt[2] - _min_pnt[2]) * _inverse_step_sizes[2]));
+
+		if (i >= _n_steps[0] || j >= _n_steps[1] || k >= _n_steps[2]) {
+			std::cout << "error computing indices " << std::endl;
+		}
+
+		_grid_quad_to_node_map[i + j * _n_steps[0] + k * n_plane].push_back(pnts[l]);
+	}
+
+#ifndef NDEBUG
+	size_t pnts_cnt(0);
+	for (size_t k(0); k < n_plane * _n_steps[2]; k++)
+		pnts_cnt += _grid_quad_to_node_map[k].size();
+
+	assert(n_pnts==pnts_cnt);
+#endif
+}
+
+template <typename POINT>
+POINT const* Grid<POINT>::getNearestPoint(double const*const pnt) const
+{
+	size_t coords[3];
+	getGridCoords(pnt, coords);
+
+	double sqr_min_dist (MathLib::sqrDist(&_min_pnt, &_max_pnt));
+	POINT* nearest_pnt(NULL);
+
+	double dists[6];
+	getPointCellBorderDistances(pnt, dists, coords);
+
+	if (calcNearestPointInGridCell(pnt, coords, sqr_min_dist, nearest_pnt)) {
+		double min_dist(sqrt(sqr_min_dist));
+		if (dists[0] >= min_dist
+			&& dists[1] >= min_dist
+			&& dists[2] >= min_dist
+			&& dists[3] >= min_dist
+			&& dists[4] >= min_dist
+			&& dists[5] >= min_dist) {
+			return nearest_pnt;
+		}
+	} else {
+		// search in all border cells for at least one neighbor
+		double sqr_min_dist_tmp;
+		POINT* nearest_pnt_tmp(NULL);
+		size_t offset(1);
+
+		while (nearest_pnt == NULL) {
+			size_t tmp_coords[3];
+			for (tmp_coords[0] = coords[0]-offset; tmp_coords[0]<coords[0]+offset; tmp_coords[0]++) {
+				for (tmp_coords[1] = coords[1]-offset; tmp_coords[1]<coords[1]+offset; tmp_coords[1]++) {
+					for (tmp_coords[2] = coords[2]-offset; tmp_coords[2]<coords[2]+offset; tmp_coords[2]++) {
+						// do not check the origin grid cell twice
+						if (!(tmp_coords[0] == coords[0] && tmp_coords[1] == coords[1] && tmp_coords[2] == coords[2])) {
+							// check if temporary grid cell coordinates are valid
+							if (tmp_coords[0] < _n_steps[0] && tmp_coords[1] < _n_steps[1] && tmp_coords[2] < _n_steps[2]) {
+								if (calcNearestPointInGridCell(pnt, tmp_coords, sqr_min_dist_tmp, nearest_pnt_tmp)) {
+									if (sqr_min_dist_tmp < sqr_min_dist) {
+										sqr_min_dist = sqr_min_dist_tmp;
+										nearest_pnt = nearest_pnt_tmp;
+									}
+								}
+							} // valid grid cell coordinates
+						} // same element
+					}  // end k
+				} // end j
+			} // end i
+			offset++;
+		} // end while
+	} // end else
+
+	double len (sqrt(MathLib::sqrDist(pnt, nearest_pnt->getCoords())));
+	// search all other grid cells within the cube with the edge nodes
+	std::vector<POINT*> pnts;
+	getPointsWithinCube(pnt, len, pnts);
+
+	const size_t n_pnts(pnts.size());
+	for (size_t k(0); k<n_pnts; k++) {
+		const double sqr_dist (MathLib::sqrDist(pnt, pnts[k]->getCoords()));
+		if (sqr_dist < sqr_min_dist) {
+			sqr_min_dist = sqr_dist;
+			nearest_pnt = pnts[k];
+		}
+	}
+
+	return nearest_pnt;
+}
+
+template <typename POINT>
+void Grid<POINT>::getPointsWithinCube(double const*const pnt, double half_len, std::vector<POINT*>& pnts) const
+{
+	double tmp_pnt[3] = {pnt[0]-half_len, pnt[1]-half_len, pnt[2]-half_len}; // min
+	size_t min_coords[3];
+	getGridCoords(tmp_pnt, min_coords);
+
+	tmp_pnt[0] = pnt[0]+half_len;
+	tmp_pnt[1] = pnt[1]+half_len;
+	tmp_pnt[2] = pnt[2]+half_len;
+	size_t max_coords[3];
+	getGridCoords(tmp_pnt, max_coords);
+
+	size_t coords[3], steps0_x_steps1(_n_steps[0] * _n_steps[1]);
+	for (coords[0] = min_coords[0]; coords[0] < max_coords[0]+1; coords[0]++) {
+		for (coords[1] = min_coords[1]; coords[1] < max_coords[1]+1; coords[1]++) {
+			const size_t coords0_p_coords1_x_steps0 (coords[0] + coords[1] * _n_steps[0]);
+			for (coords[2] = min_coords[2]; coords[2] < max_coords[2]+1; coords[2]++) {
+				// copy pnts
+				const size_t n_pnts(_grid_quad_to_node_map[coords0_p_coords1_x_steps0 + coords[2] * steps0_x_steps1].size());
+				for (size_t k(0); k<n_pnts; k++) {
+					pnts.push_back(_grid_quad_to_node_map[coords0_p_coords1_x_steps0 + coords[2] * steps0_x_steps1][k]);
+				}
+			}
+		}
+	}
+}
+
+#ifndef NDEBUG
+template <typename POINT>
+void Grid<POINT>::createGridGeometry(GeoLib::GEOObjects* geo_obj) const
+{
+	std::vector<std::string> grid_names;
+
+	GeoLib::Point const& llf (getMinPoint());
+	GeoLib::Point const& urb (getMaxPoint());
+
+	const double dx ((urb[0]-llf[0])/_n_steps[0]);
+	const double dy ((urb[1]-llf[1])/_n_steps[1]);
+	const double dz ((urb[2]-llf[2])/_n_steps[2]);
+
+	// create grid names and grid boxes as geometry
+	for (size_t i(0); i<_n_steps[0]; i++) {
+		for (size_t j(0); j<_n_steps[1]; j++) {
+			for (size_t k(0); k<_n_steps[2]; k++) {
+
+				std::string name("Grid-");
+				name += number2str<size_t>(i);
+				name +="-";
+				name += number2str<size_t>(j);
+				name += "-";
+				name += number2str<size_t> (k);
+				grid_names.push_back(name);
+
+				std::vector<GeoLib::Point*>* points (new std::vector<GeoLib::Point*>);
+				points->push_back(new GeoLib::Point(llf[0]+i*dx, llf[1]+j*dy, llf[2]+k*dz));
+				points->push_back(new GeoLib::Point(llf[0]+i*dx, llf[1]+(j+1)*dy, llf[2]+k*dz));
+				points->push_back(new GeoLib::Point(llf[0]+(i+1)*dx, llf[1]+(j+1)*dy, llf[2]+k*dz));
+				points->push_back(new GeoLib::Point(llf[0]+(i+1)*dx, llf[1]+j*dy, llf[2]+k*dz));
+				points->push_back(new GeoLib::Point(llf[0]+i*dx, llf[1]+j*dy, llf[2]+(k+1)*dz));
+				points->push_back(new GeoLib::Point(llf[0]+i*dx, llf[1]+(j+1)*dy, llf[2]+(k+1)*dz));
+				points->push_back(new GeoLib::Point(llf[0]+(i+1)*dx, llf[1]+(j+1)*dy, llf[2]+(k+1)*dz));
+				points->push_back(new GeoLib::Point(llf[0]+(i+1)*dx, llf[1]+j*dy, llf[2]+(k+1)*dz));
+				geo_obj->addPointVec(points, grid_names[grid_names.size()-1], NULL);
+
+				std::vector<GeoLib::Polyline*>* plys (new std::vector<GeoLib::Polyline*>);
+				GeoLib::Polyline* ply0 (new GeoLib::Polyline(*points));
+				for (size_t l(0); l<4; l++) {
+					ply0->addPoint(l);
+				}
+				ply0->addPoint(0);
+				plys->push_back(ply0);
+
+				GeoLib::Polyline* ply1 (new GeoLib::Polyline(*points));
+				for (size_t l(4); l<8; l++) {
+					ply1->addPoint(l);
+				}
+				ply1->addPoint(4);
+				plys->push_back(ply1);
+
+				GeoLib::Polyline* ply2 (new GeoLib::Polyline(*points));
+				ply2->addPoint(0);
+				ply2->addPoint(4);
+				plys->push_back(ply2);
+
+				GeoLib::Polyline* ply3 (new GeoLib::Polyline(*points));
+				ply3->addPoint(1);
+				ply3->addPoint(5);
+				plys->push_back(ply3);
+
+				GeoLib::Polyline* ply4 (new GeoLib::Polyline(*points));
+				ply4->addPoint(2);
+				ply4->addPoint(6);
+				plys->push_back(ply4);
+
+				GeoLib::Polyline* ply5 (new GeoLib::Polyline(*points));
+				ply5->addPoint(3);
+				ply5->addPoint(7);
+				plys->push_back(ply5);
+
+				geo_obj->addPolylineVec(plys, grid_names[grid_names.size()-1], NULL);
+			}
+		}
+	}
+	std::string merged_geo_name("Grid");
+
+	geo_obj->mergeGeometries(grid_names, merged_geo_name);
+}
+#endif
+
+template <typename POINT>
+void Grid<POINT>::getGridCoords(double const*const pnt, size_t* coords) const
+{
+	for (size_t k(0); k<3; k++) {
+		if (pnt[k] < _min_pnt[k]) {
+			coords[k] = 0;
+		} else {
+			if (pnt[k] > _max_pnt[k]) {
+				coords[k] = _n_steps[k]-1;
+			} else {
+				coords[k] = static_cast<size_t>((pnt[k]-_min_pnt[k]) * _inverse_step_sizes[k]);
+			}
+		}
+	}
+}
+
+template <typename POINT>
+bool Grid<POINT>::calcNearestPointInGridCell(double const* const pnt, size_t const* const coords,
+					double &sqr_min_dist, POINT*& nearest_pnt) const
+{
+	const size_t grid_idx (coords[0] + coords[1] * _n_steps[0] + coords[2] * _n_steps[0] * _n_steps[1]);
+	std::vector<POINT*> const& pnts(_grid_quad_to_node_map[grid_idx]);
+	if (pnts.empty()) return false;
+
+	const size_t n_pnts(pnts.size());
+	sqr_min_dist = MathLib::sqrDist(pnts[0]->getCoords(), pnt);
+	nearest_pnt = pnts[0];
+	for (size_t i(1); i < n_pnts; i++) {
+		const double sqr_dist(MathLib::sqrDist(pnts[i]->getCoords(), pnt));
+		if (sqr_dist < sqr_min_dist) {
+			sqr_min_dist = sqr_dist;
+			nearest_pnt = pnts[i];
+		}
+	}
+	return true;
+}
+
+template <typename POINT>
+void Grid<POINT>::getPointCellBorderDistances(double const*const pnt, double dists[6], size_t const* const coords) const
+{
+
+	dists[0] = (pnt[2] - _min_pnt[2] + coords[2]*_step_sizes[2]); // bottom
+	dists[5] = (_step_sizes[2] - dists[0]); // top
+
+	dists[1] = (pnt[1] - _min_pnt[1] + coords[1]*_step_sizes[1]); // front
+	dists[3] = (_step_sizes[1] - dists[1]); // back
+
+	dists[4] = (pnt[0] - _min_pnt[0] + coords[0]*_step_sizes[0]); // left
+	dists[2] = (_step_sizes[0] - dists[4]); // right
+}
+
+} // end namespace GeoLib
+
+#endif /* MESHGRID_H_ */
diff --git a/GeoLib/OctTree.h b/GeoLib/OctTree.h
new file mode 100644
index 00000000000..31b43a184a4
--- /dev/null
+++ b/GeoLib/OctTree.h
@@ -0,0 +1,241 @@
+/*
+ * @file OctTree.h
+ *
+ *  Created on: Feb 27, 2012
+ *      Author: TF
+ */
+
+#ifndef OCTTREE_H_
+#define OCTTREE_H_
+
+namespace GeoLib {
+
+template <typename POINT> class OctTree {
+public:
+
+	static OctTree<POINT>* createOctTree(POINT & ll, POINT & ur, size_t max_points_per_node)
+	{
+		const double dx(ur[0] - ll[0]);
+		const double dy(ur[1] - ll[1]);
+		const double dz(ur[2] - ll[2]);
+
+		if (dx >= dy && dx >= dz) {
+			ll[1] -= (dx-dy)/2.0;
+			ur[1] += (dx-dy)/2.0;
+			ll[2] -= (dx-dz)/2.0;
+			ur[2] += (dx-dz)/2.0;
+		} else {
+			if (dy >= dx && dy >= dz) {
+				ll[0] -= (dy-dx)/2.0;
+				ur[0] += (dy-dx)/2.0;
+				ll[2] -= (dy-dz)/2.0;
+				ur[2] += (dy-dz)/2.0;
+			} else {
+				ll[0] -= (dz-dx)/2.0;
+				ur[0] += (dz-dx)/2.0;
+				ll[1] -= (dz-dy)/2.0;
+				ur[1] += (dz-dy)/2.0;
+			}
+		}
+
+		OctTree<POINT>::_max_points_per_node = max_points_per_node;
+		return new OctTree<POINT>(ll, ur);
+	}
+
+	virtual ~OctTree()
+	{
+		for (size_t k(0); k < 8; k++)
+			delete _childs[k];
+	}
+
+	/**
+	 * This method adds the given point to the OctTree. If necessary,
+	 * the OctTree will be extended.
+	 * @param pnt the point
+	 * @return If the point can be inserted the method returns true, else false.
+	 */
+	bool addPoint (POINT* pnt)
+	{
+		if ((*pnt)[0] < _ll[0]) return false;
+		if ((*pnt)[0] > _ur[0]) return false;
+		if ((*pnt)[1] < _ll[1]) return false;
+		if ((*pnt)[1] > _ur[1]) return false;
+		if ((*pnt)[2] < _ll[2]) return false;
+		if ((*pnt)[2] > _ur[2]) return false;
+
+		if (!_is_leaf) {
+			for (size_t k(0); k < 8; k++) {
+				if (_childs[k]->addPoint (pnt)) {
+					return true;
+				}
+			}
+		}
+
+		// check if point is already in OctTree
+		bool pnt_in_tree (false);
+		for (size_t k(0); k < _pnts.size() && !pnt_in_tree; k++) {
+			const double sqr_dist (MathLib::sqrDist( (_pnts[k])->getCoords(), pnt->getCoords() ));
+			if (sqr_dist < std::numeric_limits<double>::epsilon())
+				pnt_in_tree = true;
+		}
+		if (!pnt_in_tree)
+			_pnts.push_back (pnt);
+		else
+			return false;
+
+		if (_pnts.size () > OctTree<POINT>::_max_points_per_node)
+			splitNode ();
+		return true;
+	}
+
+	/**
+	 * range query - returns all points inside the range (min[0], max[0]) x (min[1], max[1]) x (min[2], max[2])
+	 * @param min
+	 * @param max
+	 * @param pnts
+	 */
+	void getPointsInRange(POINT const& min, POINT const& max, std::vector<POINT*> &pnts) const
+	{
+		if (_ur[0] < min[0]) return;
+		if (_ur[1] < min[1]) return;
+		if (_ur[2] < min[2]) return;
+
+		if (max[0] < _ll[0]) return;
+		if (max[1] < _ll[1]) return;
+		if (max[2] < _ll[2]) return;
+
+		if (_is_leaf) {
+			typename std::vector<POINT*>::const_iterator it;
+			for (it = (_pnts.begin()); it != _pnts.end(); it++) {
+				pnts.push_back(*it);
+			}
+		} else {
+			for (size_t k(0); k<8; k++) {
+				_childs[k]->getPointsInRange(min, max, pnts);
+			}
+		}
+	}
+
+private:
+	enum OctTreeQuadrant {
+		NEL = 0, //!< north east lower
+		NWL, //!< north west lower
+		SWL, //!< south west lower
+		SEL, //!< south east lower
+		NEU, //!< south west upper
+		NWU, //!< south west upper
+		SWU, //!< south west upper
+		SEU //!< south east upper
+	};
+
+	/**
+	 * private constructor
+	 * @param ll lower left point
+	 * @param ur upper right point
+	 * @return
+	 */
+	OctTree (POINT const& ll, POINT const& ur) :
+		_ll (ll), _ur (ur), _is_leaf (true)
+	{
+		// init childs
+		for (size_t k(0); k < 8; k++)
+			_childs[k] = NULL;
+	}
+
+	void splitNode ()
+	{
+		const double x_mid((_ur[0] + _ll[0]) / 2.0);
+		const double y_mid((_ur[1] + _ll[1]) / 2.0);
+		const double z_mid((_ur[2] + _ll[2]) / 2.0);
+		POINT p0(x_mid, y_mid, _ll[2]), p1(_ur[0], _ur[1], z_mid);
+
+		// create child NEL
+		_childs[NEL] = new OctTree<POINT> (p0, p1);
+
+		// create child NWL
+		p0[0] = _ll[0];
+		p1[0] = x_mid;
+		_childs[NWL] = new OctTree<POINT> (p0, p1);
+
+		// create child SWL
+		p0[1] = _ll[1];
+		p1[1] = y_mid;
+		_childs[SWL] = new OctTree<POINT> (_ll, p1);
+
+		// create child NEU
+		_childs[NEU] = new OctTree<POINT> (p1, _ur);
+
+		// create child SEL
+		p0[0] = x_mid;
+		p1[0] = _ur[0];
+		_childs[SEL] = new OctTree<POINT> (p0, p1);
+
+		// create child NWU
+		p0[0] = _ll[0];
+		p0[1] = y_mid;
+		p0[2] = z_mid;
+		p1[0] = x_mid;
+		p1[1] = _ur[1];
+		p1[2] = _ur[2];
+		_childs[NWU] = new OctTree<POINT> (p0, p1);
+
+		// create child SWU
+		p0[1] = _ll[1];
+		p1[1] = y_mid;
+		_childs[SWU] = new OctTree<POINT> (p0, p1);
+
+		// create child SEU
+		p0[0] = x_mid;
+		p1[0] = _ur[0];
+		p1[1] = y_mid;
+		p1[2] = _ur[2];
+		_childs[SEU] = new OctTree<POINT> (p0, p1);
+
+		// distribute points to sub quadtrees
+		const size_t n_pnts(_pnts.size());
+		for (size_t j(0); j < n_pnts; j++) {
+			bool nfound(true);
+			for (size_t k(0); k < 8 && nfound; k++) {
+				if (_childs[k]->addPoint(_pnts[j])) {
+					nfound = false;
+				}
+			}
+		}
+		_pnts.clear();
+		_is_leaf = false;
+	}
+
+	/**
+	 * childs are sorted:
+	 *   _childs[0] is north east lower child
+	 *   _childs[1] is north west lower child
+	 *   _childs[2] is south west lower child
+	 *   _childs[3] is south east lower child
+	 *   _childs[4] is north east upper child
+	 *   _childs[5] is north west upper child
+	 *   _childs[6] is south west upper child
+	 *   _childs[7] is south east upper child
+	 */
+	OctTree<POINT>* _childs[8];
+	/**
+	 * lower left front face point of the cube
+	 */
+	POINT const _ll;
+	/**
+	 * upper right back face point of the cube
+	 */
+	POINT const _ur;
+
+	std::vector<POINT*> _pnts;
+	bool _is_leaf;
+	/**
+	 * maximum number of points per leaf
+	 */
+	static size_t _max_points_per_node;
+};
+
+template <typename POINT> size_t OctTree<POINT>::_max_points_per_node = 0;
+
+} // end namespace GeoLib
+
+#endif /* OCTTREE_H_ */
-- 
GitLab