1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
|
/************************************************************************
*
* Copyright (C) 2017-2023 IRCAD France
* Copyright (C) 2017-2020 IHU Strasbourg
*
* This file is part of Sight.
*
* Sight is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Sight is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with Sight. If not, see <https://www.gnu.org/licenses/>.
*
***********************************************************************/
#include "geometry/data/point_list.hpp"
#include <data/point.hpp>
#include <data/point_list.hpp>
#include <geometry/data/matrix4.hpp>
#include <glm/geometric.hpp>
#include <glm/vec3.hpp>
#include <cmath>
#include <list>
namespace sight::geometry::data
{
//-----------------------------------------------------------------------------
sight::data::array::sptr point_list::compute_distance(
sight::data::point_list::sptr _point_list1,
sight::data::point_list::sptr _point_list2
)
{
SIGHT_ASSERT(
"the 2 pointLists must have the same number of points",
_point_list1->get_points().size() == _point_list2->get_points().size()
);
const auto points1 = _point_list1->get_points();
const auto points2 = _point_list2->get_points();
const std::size_t size = points1.size();
sight::data::array::sptr output_array = std::make_shared<sight::data::array>();
output_array->resize({size}, sight::core::type::DOUBLE);
const auto dump_lock = output_array->dump_lock();
auto distance_array_itr = output_array->begin<double>();
for(std::size_t i = 0 ; i < size ; ++i)
{
const sight::data::point::point_coord_array_t tmp1 = points1[i]->get_coord();
const sight::data::point::point_coord_array_t tmp2 = points2[i]->get_coord();
const glm::dvec3 pt1 = glm::dvec3(tmp1[0], tmp1[1], tmp1[2]);
const glm::dvec3 pt2 = glm::dvec3(tmp2[0], tmp2[1], tmp2[2]);
*distance_array_itr = glm::distance(pt1, pt2);
++distance_array_itr;
}
return output_array;
}
//------------------------------------------------------------------------------
void point_list::transform(
sight::data::point_list::sptr& _point_list,
const sight::data::matrix4::csptr& _matrix
)
{
const sight::data::point_list::container_t points = _point_list->get_points();
const std::size_t size = points.size();
for(std::size_t i = 0 ; i < size ; ++i)
{
sight::data::point& pt = *points[i];
// Transform the current point with the input matrix
sight::geometry::data::multiply(*_matrix, pt, pt);
}
}
//------------------------------------------------------------------------------
void point_list::associate(
const sight::data::point_list::csptr& _point_list1,
sight::data::point_list::sptr _point_list2
)
{
SIGHT_ASSERT(
"the 2 pointLists must have the same number of points",
_point_list1->get_points().size() == _point_list2->get_points().size()
);
const sight::data::point_list::container_t points1 = _point_list1->get_points();
const sight::data::point_list::container_t points2 = _point_list2->get_points();
const std::size_t size = points1.size();
// Transform first point list into vector< glm::dvec3 > (no erase is performed)
std::vector<glm::dvec3> vec1;
vec1.reserve(size);
//and second one into a list (since we will erase associated points)
std::list<glm::dvec3> list2;
for(std::size_t i = 0 ; i < size ; ++i)
{
const sight::data::point::point_coord_array_t tmp1 = points1[i]->get_coord();
const sight::data::point::point_coord_array_t tmp2 = points2[i]->get_coord();
// Add the point to vector/list
vec1.emplace_back(tmp1[0], tmp1[1], tmp1[2]);
list2.emplace_back(tmp2[0], tmp2[1], tmp2[2]);
}
std::size_t index = 0;
for(auto point1 : vec1)
{
// Identify the closest point
double distance_min = std::numeric_limits<double>::max();
std::list<glm::dvec3>::iterator it_closest_point;
for(auto it2 = list2.begin() ; it2 != list2.end() ; ++it2)
{
const glm::dvec3 point2 = *it2;
const double distance = glm::distance(point1, point2);
if(distance < distance_min)
{
distance_min = distance;
it_closest_point = it2;
}
}
sight::data::point::point_coord_array_t point_coord;
point_coord[0] = it_closest_point->x;
point_coord[1] = it_closest_point->y;
point_coord[2] = it_closest_point->z;
const sight::data::point::sptr& pt = points2[index];
pt->set_coord(point_coord);
++index;
// Erase the already matched point
list2.erase(it_closest_point);
}
}
//------------------------------------------------------------------------------
sight::data::point::sptr point_list::remove_closest_point(
const sight::data::point_list::sptr& _point_list,
const sight::data::point::csptr& _point,
float _delta
)
{
// Initial data
const auto& list = _point_list->get_points();
if(!list.empty())
{
const auto& coord1 = _point->get_coord();
const glm::vec3 p1 {coord1[0], coord1[1], coord1[2]};
// Data to find the closest point
float closest = std::numeric_limits<float>::max();
sight::data::point::sptr point = nullptr;
std::size_t index = 0;
bool point_is_found = false;
// Find the closest one
for(std::size_t i = 0 ; i < list.size() ; ++i)
{
const auto& coord2 = list[i]->get_coord();
const glm::vec3 p2 {coord2[0], coord2[1], coord2[2]};
float temp_closest = NAN;
if((temp_closest = glm::distance(p1, p2)) < _delta && temp_closest < closest)
{
closest = temp_closest;
point = list[i];
index = i;
point_is_found = true;
}
}
// Remove the closest point if it has been found
if(point_is_found)
{
_point_list->remove(index);
}
return point;
}
return nullptr;
}
//-----------------------------------------------------------------------------
} // namespace sight::geometry::data
|