diff --git a/GeoLib/Grid.h b/GeoLib/Grid.h index a98167d42050b3a49395811dd627a54003022713..626e4456af51b889a026a18bd6b5d99f5ea21268 100644 --- a/GeoLib/Grid.h +++ b/GeoLib/Grid.h @@ -55,7 +55,11 @@ public: */ template <typename InputIterator> Grid(InputIterator first, InputIterator last, std::size_t max_num_per_grid_cell = 512) : - GeoLib::AABB<POINT>(first, last), _grid_cell_nodes_map(NULL) + GeoLib::AABB<POINT>(first, last), + _n_steps({{1,1,1}}), + _step_sizes({{0.0,0.0,0.0}}), + _inverse_step_sizes({{0.0,0.0,0.0}}), + _grid_cell_nodes_map(nullptr) { std::size_t n_pnts(std::distance(first, last)); @@ -70,60 +74,7 @@ public: delta[k] = this->_max_pnt[k] - this->_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<std::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<std::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<std::size_t> (ceil(n_pnts / (double) max_num_per_grid_cell)); - } else { - // 2d case - if (fabs(delta[1]) < std::numeric_limits<double>::epsilon()) { - // y = const - _n_steps[0] = static_cast<std::size_t> (ceil(sqrt(n_pnts * delta[0] / (max_num_per_grid_cell * delta[2])))); - _n_steps[1] = 1; - _n_steps[2] = static_cast<std::size_t> (ceil(_n_steps[0] * delta[2] / delta[0])); - } else { - if (fabs(delta[2]) < std::numeric_limits<double>::epsilon()) { - // z = const - _n_steps[0] = static_cast<std::size_t> (ceil(sqrt(n_pnts * delta[0] / (max_num_per_grid_cell * delta[1])))); - _n_steps[1] = static_cast<std::size_t> (ceil(_n_steps[0] * delta[1] / delta[0])); - _n_steps[2] = 1; - } else { - // x = const - _n_steps[0] = 1; - _n_steps[1] = static_cast<std::size_t> (ceil(n_pnts * delta[1] / (max_num_per_grid_cell * delta[2]))); - _n_steps[2] = static_cast<std::size_t> (ceil(_n_steps[1] * delta[2] / delta[1])); - } - } - } - } - } - } else { - // 3d case - _n_steps[0] = static_cast<std::size_t> (ceil(pow(n_pnts * delta[0] * delta[0] - / (max_num_per_grid_cell * delta[1] * delta[2]), 1. / 3.))); - _n_steps[1] = std::max(static_cast<std::size_t>(1), std::min(static_cast<std::size_t> (ceil(_n_steps[0] * delta[1] / delta[0])), static_cast<std::size_t>(100))); - _n_steps[2] = std::max(static_cast<std::size_t>(1), std::min(static_cast<std::size_t> (ceil(_n_steps[0] * delta[2] / delta[0])), static_cast<std::size_t>(100))); - } + initNumberOfSteps(max_num_per_grid_cell, n_pnts, delta); const std::size_t n_plane(_n_steps[0] * _n_steps[1]); _grid_cell_nodes_map = new std::vector<POINT*>[n_plane * _n_steps[2]]; @@ -300,6 +251,61 @@ public: #endif private: + void initNumberOfSteps(std::size_t max_num_per_grid_cell, std::size_t n_pnts, double delta[3]) + { + // *** 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] + const double eps(std::numeric_limits<double>::epsilon()); + if (fabs(delta[0]) < eps) { // dx == 0 + if(fabs(delta[1]) < eps) { // dy == 0 + if(fabs(delta[2]) < eps) { // degenerated case, dx == 0, dy == 0, dz == 0 + WARN("Grid constructor: Bounding volume [%f,%f] x [%f,%f] x [%f,%f] too small.", + this->_min_pnt[0], this->_max_pnt[0], + this->_min_pnt[1], this->_max_pnt[1], + this->_min_pnt[2], this->_max_pnt[2] + ); + } else { // 1d case: dx == 0, dy == 0, dz != 0 + _n_steps[0] = 1; + _n_steps[1] = 1; + _n_steps[2] = static_cast<std::size_t> (ceil(n_pnts / (double) max_num_per_grid_cell)); + } + } else { // dy != 0 + if(fabs(delta[2]) < eps) { // 1d case: dx == 0, dy != 0, dz == 0 + _n_steps[0] = 1; + _n_steps[1] = static_cast<std::size_t> (ceil(n_pnts / (double) max_num_per_grid_cell)); + _n_steps[2] = 1; + } else { // 2d case: dx == 0, dy != 0, dz != 0 + _n_steps[0] = 1; + _n_steps[1] = static_cast<std::size_t> (ceil(sqrt(n_pnts * delta[1] / (max_num_per_grid_cell * delta[2])))); + _n_steps[2] = static_cast<std::size_t> (ceil(n_pnts / (double) max_num_per_grid_cell)); + } + } + } else { // dx != 0 + if(fabs(delta[1]) < eps) { // dy == 0 + if(fabs(delta[2]) < eps) { // 1d case: dx != 0, dy == 0, dz == 0 + _n_steps[0] = static_cast<std::size_t> (ceil(n_pnts / (double) max_num_per_grid_cell)); + _n_steps[1] = 1; + _n_steps[2] = 1; + } else { // 2d case: dx != 0, dy == 0, dz != 0 + _n_steps[0] = static_cast<std::size_t> (ceil(sqrt(n_pnts * delta[0] / (max_num_per_grid_cell * delta[2])))); + _n_steps[1] = 1; + _n_steps[2] = static_cast<std::size_t> (ceil(_n_steps[0] * delta[2] / delta[0])); + } + } else { // dy != 0 + if(fabs(delta[2]) < eps) { // 2d case: dx != 0, dy != 0, dz == 0 + _n_steps[0] = static_cast<std::size_t> (ceil(sqrt(n_pnts * delta[0] / (max_num_per_grid_cell * delta[1])))); + _n_steps[1] = static_cast<std::size_t> (ceil(_n_steps[0] * delta[1] / delta[0])); + _n_steps[2] = 1; + } else { // 3d case: dx != 0, dy != 0, dz != 0 + _n_steps[0] = static_cast<std::size_t> (ceil(pow(n_pnts * delta[0] * delta[0] + / (max_num_per_grid_cell * delta[1] * delta[2]), 1. / 3.))); + _n_steps[1] = std::max(static_cast<std::size_t>(1), std::min(static_cast<std::size_t> (ceil(_n_steps[0] * delta[1] / delta[0])), static_cast<std::size_t>(100))); + _n_steps[2] = std::max(static_cast<std::size_t>(1), std::min(static_cast<std::size_t> (ceil(_n_steps[0] * delta[2] / delta[0])), static_cast<std::size_t>(100))); + } + } + } + } + /** * 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 @@ -368,9 +374,9 @@ private: static POINT const* copyOrAddress(POINT const& p) { return &p; } static POINT* copyOrAddress(POINT* p) { return p; } - double _step_sizes[3]; - double _inverse_step_sizes[3]; - std::size_t _n_steps[3]; + std::array<std::size_t,3> _n_steps; + std::array<double, 3> _step_sizes; + std::array<double, 3> _inverse_step_sizes; /** * This is an array that stores pointers to POINT objects. */ diff --git a/Tests/GeoLib/TestGrid.cpp b/Tests/GeoLib/TestGrid.cpp index 933aea96c45776bce3f9455f2c369dcdd6997b36..fcb906fbd29409245e91470a3345118fe297e64d 100644 --- a/Tests/GeoLib/TestGrid.cpp +++ b/Tests/GeoLib/TestGrid.cpp @@ -2,7 +2,7 @@ * @file TestGrid.cpp * @author Thomas Fischer * @date Mar 22, 2013 - * @brief + * @brief Tests for class GeoLib::Grid. * * @copyright * Copyright (c) 2013, OpenGeoSys Community (http://www.opengeosys.org) @@ -11,6 +11,8 @@ * http://www.opengeosys.org/LICENSE.txt */ +#include <memory> + #include "gtest/gtest.h" #include "GeoLib/Point.h" @@ -30,6 +32,7 @@ TEST(GeoLib, InsertOnePointInGrid) std::vector<GeoLib::Point*> pnts; pnts.push_back(new GeoLib::Point(0.0,0.0,0.0)); ASSERT_NO_THROW(GeoLib::Grid<GeoLib::Point> grid(pnts.begin(), pnts.end())); + std::for_each(pnts.begin(), pnts.end(), std::default_delete<GeoLib::Point>()); } TEST(GeoLib, InsertTwoPointsInGrid) @@ -38,6 +41,7 @@ TEST(GeoLib, InsertTwoPointsInGrid) pnts.push_back(new GeoLib::Point(4.5, -400.0, 0.0)); pnts.push_back(new GeoLib::Point(50, -300.0, 0.0)); ASSERT_NO_THROW(GeoLib::Grid<GeoLib::Point> grid(pnts.begin(), pnts.end())); + std::for_each(pnts.begin(), pnts.end(), std::default_delete<GeoLib::Point>()); } @@ -59,6 +63,18 @@ TEST(GeoLib, InsertManyPointsInGrid) } ASSERT_NO_THROW(GeoLib::Grid<GeoLib::Point> grid(pnts.begin(), pnts.end())); + std::for_each(pnts.begin(), pnts.end(), std::default_delete<GeoLib::Point>()); +} + +TEST(GeoLib, InsertPointsWithSameXCoordinateInGrid) +{ + std::vector<GeoLib::Point*> pnts; + pnts.push_back(new GeoLib::Point(0,0,0)); + pnts.push_back(new GeoLib::Point(0,1,0)); + pnts.push_back(new GeoLib::Point(0,1,0.1)); + + GeoLib::Grid<GeoLib::Point> grid(pnts.begin(), pnts.end()); + std::for_each(pnts.begin(), pnts.end(), std::default_delete<GeoLib::Point>()); } TEST(GeoLib, SearchNearestPointInGrid) @@ -71,6 +87,9 @@ TEST(GeoLib, SearchNearestPointInGrid) GeoLib::Point p0(0,10,10); GeoLib::Point* res(grid->getNearestPoint(p0.getCoords())); ASSERT_EQ(sqrt(MathLib::sqrDist(*res, *pnts[0])), 0.0); + + delete grid; + std::for_each(pnts.begin(), pnts.end(), std::default_delete<GeoLib::Point>()); } TEST(GeoLib, SearchNearestPointsInDenseGrid) @@ -125,4 +144,6 @@ TEST(GeoLib, SearchNearestPointsInDenseGrid) } } + delete grid; + std::for_each(pnts.begin(), pnts.end(), std::default_delete<GeoLib::PointWithID>()); } diff --git a/Tests/MeshLib/TestMeshNodeSearch.cpp b/Tests/MeshLib/TestMeshNodeSearch.cpp index 1422b1e27d7bc57a207536f13290f619e2c85b82..ab9c785a7a4b065c924f4e7c7a289c5bb95fbcf0 100644 --- a/Tests/MeshLib/TestMeshNodeSearch.cpp +++ b/Tests/MeshLib/TestMeshNodeSearch.cpp @@ -77,15 +77,15 @@ TEST_F(MeshLibMeshNodeSearchInSimpleQuadMesh, PointSearch) pnt[0] = 0.051; pnt[1] = 0.049; - ASSERT_EQ(1, mesh_node_searcher.getMeshNodeIDForPoint(pnt)); + ASSERT_EQ(1u, mesh_node_searcher.getMeshNodeIDForPoint(pnt)); pnt[0] = 0.049; pnt[1] = 0.051; - ASSERT_EQ(100, mesh_node_searcher.getMeshNodeIDForPoint(pnt)); + ASSERT_EQ(100u, mesh_node_searcher.getMeshNodeIDForPoint(pnt)); pnt[0] = 0.051; pnt[1] = 0.051; - ASSERT_EQ(101, mesh_node_searcher.getMeshNodeIDForPoint(pnt)); + ASSERT_EQ(101u, mesh_node_searcher.getMeshNodeIDForPoint(pnt)); pnt[0] = 9.951; pnt[1] = 9.951; @@ -114,7 +114,7 @@ TEST_F(MeshLibMeshNodeSearchInSimpleQuadMesh, PolylineSearch) MeshGeoToolsLib::MeshNodeSearcher mesh_node_searcher(*_quad_mesh); std::vector<std::size_t> const& found_ids_ply0(mesh_node_searcher.getMeshNodeIDsAlongPolyline(ply0)); - ASSERT_EQ(100, found_ids_ply0.size()); + ASSERT_EQ(100u, found_ids_ply0.size()); for (std::size_t k(0); k<found_ids_ply0.size(); k++) ASSERT_EQ(k, found_ids_ply0[k]); @@ -123,7 +123,7 @@ TEST_F(MeshLibMeshNodeSearchInSimpleQuadMesh, PolylineSearch) ply1.addPoint(3); std::vector<std::size_t> const& found_ids_ply1(mesh_node_searcher.getMeshNodeIDsAlongPolyline(ply1)); - ASSERT_EQ(100, found_ids_ply1.size()); + ASSERT_EQ(100u, found_ids_ply1.size()); for (std::size_t k(0); k<found_ids_ply1.size(); k++) ASSERT_EQ(k, found_ids_ply1[k]); @@ -133,7 +133,7 @@ TEST_F(MeshLibMeshNodeSearchInSimpleQuadMesh, PolylineSearch) std::vector<std::size_t> const& found_ids_ply2(mesh_node_searcher.getMeshNodeIDsAlongPolyline(ply2)); std::size_t offset((_number_of_subdivisions_per_direction+1)*_number_of_subdivisions_per_direction); - ASSERT_EQ(100, found_ids_ply2.size()); + ASSERT_EQ(100u, found_ids_ply2.size()); for (std::size_t k(0); k<found_ids_ply2.size(); k++) ASSERT_EQ(offset + k, found_ids_ply2[k]); @@ -142,7 +142,7 @@ TEST_F(MeshLibMeshNodeSearchInSimpleQuadMesh, PolylineSearch) ply3.addPoint(7); std::vector<std::size_t> const& found_ids_ply3(mesh_node_searcher.getMeshNodeIDsAlongPolyline(ply3)); - ASSERT_EQ(100, found_ids_ply3.size()); + ASSERT_EQ(100u, found_ids_ply3.size()); for (std::size_t k(0); k<found_ids_ply3.size(); k++) ASSERT_EQ(offset + k, found_ids_ply3[k]); @@ -152,7 +152,7 @@ TEST_F(MeshLibMeshNodeSearchInSimpleQuadMesh, PolylineSearch) ply4.addPoint(6); std::vector<std::size_t> const& found_ids_ply4(mesh_node_searcher.getMeshNodeIDsAlongPolyline(ply4)); - ASSERT_EQ(100, found_ids_ply4.size()); + ASSERT_EQ(100u, found_ids_ply4.size()); for (std::size_t k(0); k<found_ids_ply4.size(); k++) ASSERT_EQ(k*(_number_of_subdivisions_per_direction+1), found_ids_ply4[k]); @@ -162,7 +162,7 @@ TEST_F(MeshLibMeshNodeSearchInSimpleQuadMesh, PolylineSearch) ply5.addPoint(7); std::vector<std::size_t> const& found_ids_ply5(mesh_node_searcher.getMeshNodeIDsAlongPolyline(ply5)); - ASSERT_EQ(100, found_ids_ply5.size()); + ASSERT_EQ(100u, found_ids_ply5.size()); for (std::size_t k(0); k<found_ids_ply5.size(); k++) ASSERT_EQ(k*(_number_of_subdivisions_per_direction+1)+_number_of_subdivisions_per_direction, found_ids_ply5[k]); @@ -172,7 +172,7 @@ TEST_F(MeshLibMeshNodeSearchInSimpleQuadMesh, PolylineSearch) ply6.addPoint(5); std::vector<std::size_t> const& found_ids_ply6(mesh_node_searcher.getMeshNodeIDsAlongPolyline(ply6)); - ASSERT_EQ(100, found_ids_ply6.size()); + ASSERT_EQ(100u, found_ids_ply6.size()); for (std::size_t k(0); k<found_ids_ply6.size(); k++) ASSERT_EQ(k*(_number_of_subdivisions_per_direction+1)+k, found_ids_ply6[k]);