fw4spl
ools/src/fwDataTools/helper/PointList.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2017-2018.
3  * Distributed under the terms of the GNU Lesser General Public License (LGPL) as
4  * published by the Free Software Foundation.
5  * ****** END LICENSE BLOCK ****** */
6 
7 #include "fwDataTools/helper/PointList.hpp"
8 
9 #include <fwDataTools/helper/Array.hpp>
10 #include <fwDataTools/TransformationMatrix3D.hpp>
11 
12 #include <fwData/Point.hpp>
13 #include <fwData/PointList.hpp>
14 
15 #include <glm/geometric.hpp>
16 #include <glm/vec3.hpp>
17 
18 #include <list>
19 
20 namespace fwDataTools
21 {
22 namespace helper
23 {
24 
25 //-----------------------------------------------------------------------------
26 
28 {
29 }
30 
31 //-----------------------------------------------------------------------------
32 
34 {
35 }
36 
37 //-----------------------------------------------------------------------------
38 
39 ::fwData::Array::sptr
40 PointList::computeDistance(::fwData::PointList::sptr _pointList1,
41  ::fwData::PointList::sptr _pointList2)
42 {
43  SLM_ASSERT("the 2 pointLists must have the same number of points",
44  _pointList1->getPoints().size() == _pointList2->getPoints().size() );
45 
46  const ::fwData::PointList::PointListContainer points1 = _pointList1->getPoints();
47  const ::fwData::PointList::PointListContainer points2 = _pointList2->getPoints();
48  const size_t size = points1.size();
49 
50  ::fwData::Array::sptr outputArray = ::fwData::Array::New();
51  ::fwData::Array::SizeType arraySize;
52  arraySize.push_back(size);
53  outputArray->resize("double", arraySize, 1, true);
54  ::fwDataTools::helper::Array arrayHelper(outputArray);
55  double* distanceArray = arrayHelper.begin<double>();
56 
57  for (size_t i = 0; i < size; ++i)
58  {
59  const ::fwData::Point::PointCoordArrayType tmp1 = points1[i]->getCoord();
60  const ::fwData::Point::PointCoordArrayType tmp2 = points2[i]->getCoord();
61  const ::glm::dvec3 pt1 = ::glm::dvec3(tmp1[0], tmp1[1], tmp1[2]);
62  const ::glm::dvec3 pt2 = ::glm::dvec3(tmp2[0], tmp2[1], tmp2[2]);
63  distanceArray[i] = ::glm::distance(pt1, pt2);
64  }
65 
66  return outputArray;
67 }
68 
69 //------------------------------------------------------------------------------
70 
71 void PointList::transform(::fwData::PointList::sptr& _pointList,
72  const ::fwData::TransformationMatrix3D::csptr& _matrix)
73 {
74  ::fwData::PointList::PointListContainer points = _pointList->getPoints();
75  const size_t size = points.size();
76 
77  for(size_t i = 0; i < size; ++i)
78  {
79  ::fwData::Point::sptr& pt = points[i];
80 
81  // Transform the current point with the input matrix
83  }
84 }
85 
86 //------------------------------------------------------------------------------
87 
88 void PointList::associate(const ::fwData::PointList::csptr& _pointList1,
89  ::fwData::PointList::sptr _pointList2)
90 {
91  SLM_ASSERT("the 2 pointLists must have the same number of points",
92  _pointList1->getPoints().size() == _pointList2->getPoints().size() );
93 
94  ::fwData::PointList::PointListContainer points1 = _pointList1->getPoints();
95  ::fwData::PointList::PointListContainer points2 = _pointList2->getPoints();
96 
97  const size_t size = points1.size();
98 
99  // Transform first point list into vector< ::glm::dvec3 > (no erase is performed)
100  std::vector< ::glm::dvec3 > vec1;
101  vec1.reserve(size);
102  //and second one into a list (since we will erase associated points)
103  std::list< ::glm::dvec3 > list2;
104 
105  for(size_t i = 0; i < size; ++i)
106  {
107  const ::fwData::Point::PointCoordArrayType tmp1 = points1[i]->getCoord();
108  const ::fwData::Point::PointCoordArrayType tmp2 = points2[i]->getCoord();
109 
110  // Add the point to vector/list
111  vec1.push_back(::glm::dvec3( tmp1[0], tmp1[1], tmp1[2]));
112  list2.push_back(::glm::dvec3( tmp2[0], tmp2[1], tmp2[2]));
113  }
114 
115  size_t index = 0;
116  for(auto point1 : vec1)
117  {
118  // Identify the closest point
119  double distanceMin = std::numeric_limits<double>::max();
120  std::list< ::glm::dvec3 >::iterator itClosestPoint;
121 
122  std::list< ::glm::dvec3 >::iterator it2 = list2.begin();
123  for(; it2 != list2.end(); it2++)
124  {
125  const ::glm::dvec3 point2 = *it2;
126  const double distance = ::glm::distance(point1, point2);
127  if(distance < distanceMin)
128  {
129  distanceMin = distance;
130  itClosestPoint = it2;
131  }
132  }
133 
134  ::fwData::Point::PointCoordArrayType pointCoord;
135  pointCoord[0] = itClosestPoint->x;
136  pointCoord[1] = itClosestPoint->y;
137  pointCoord[2] = itClosestPoint->z;
138 
139  ::fwData::Point::sptr pt = points2[index];
140  pt->setCoord(pointCoord);
141  ++index;
142 
143  // Erase the already matched point
144  list2.erase(itClosestPoint);
145  }
146 }
147 
148 //------------------------------------------------------------------------------
149 
150 const ::fwData::Point::sptr PointList::removeClosestPoint(::fwData::PointList::sptr& _pointList,
151  const ::fwData::Point::sptr& _point, float _delta)
152 {
153  // Initial data
154  const auto& list = _pointList->getPoints();
155  if(list.size() > 0)
156  {
157  const auto& coord1 = _point->getCoord();
158  const ::glm::vec3 p1{coord1[0], coord1[1], coord1[2]};
159 
160  // Data to find the closest point
161  float closest = std::numeric_limits<float>::max();
162  ::fwData::Point::sptr point = nullptr;
163  size_t index = -1;
164 
165  // Find the closest one
166  for(size_t i = 0; i < list.size(); ++i)
167  {
168  const auto& coord2 = list[i]->getCoord();
169  const ::glm::vec3 p2{coord2[0], coord2[1], coord2[2]};
170 
171  float tempClosest;
172  if((tempClosest = ::glm::distance(p1, p2)) < _delta && tempClosest < closest)
173  {
174  closest = tempClosest;
175  point = list[i];
176  index = i;
177  }
178 
179  }
180 
181  // Remove the closest point if it has been found
182  if(index != -1)
183  {
184  _pointList->remove(index);
185  }
186  return point;
187  }
188  return nullptr;
189 }
190 
191 //-----------------------------------------------------------------------------
192 
193 } // namespace helper
194 } // namespace fwDataTools
std::vector< size_t > SizeType
Array size type.
static FWDATATOOLS_API void transform(::fwData::PointList::sptr &_pointList, const ::fwData::TransformationMatrix3D::csptr &_matrix)
Transform a pointList with a transformation matrix.
The namespace fwDataTools contains classes which provide helpers to manipulate fwData::Object. *.
static FWDATATOOLS_APIconst::fwData::Point::sptr removeClosestPoint(::fwData::PointList::sptr &_pointList, const ::fwData::Point::sptr &_point, float _delta)
removeClosestPoint: removes the closest point from a reference point
FWDATATOOLS_API PointList()
Constructor. Does nothing.
static FWDATATOOLS_API::fwData::Array::sptr computeDistance(::fwData::PointList::sptr _pointList1,::fwData::PointList::sptr _pointList2)
Computes the point-to-point distance between 2 pointlists.
virtual FWDATATOOLS_API char * begin()
Returns the begining/end of the buffer interpreted as a char buffer.
#define SLM_ASSERT(message, cond)
work like &#39;assert&#39; from &#39;cassert&#39;, with in addition a message logged by spylog (with FATAL loglevel) ...
Definition: spyLog.hpp:308
static FWDATATOOLS_API void multiply(const ::fwData::TransformationMatrix3D::csptr &_trfA, const ::fwData::TransformationMatrix3D::csptr &_trfB,::fwData::TransformationMatrix3D::sptr &_output)
Multiply two matrices.
static FWDATATOOLS_API void associate(const ::fwData::PointList::csptr &_pointList1,::fwData::PointList::sptr _pointList2)
Associate 2 pointLists: Take 2 pointLists as input and re-order the second one, so that the points at...
FWDATATOOLS_API ~PointList()
Destructor. Does nothing.
Helper to manage array buffer. Lock the buffer before to modify it.