ITK  6.0.0
Insight Toolkit
itkQuadEdgeMeshDecimationQuadricElementHelper.h
Go to the documentation of this file.
1/*=========================================================================
2 *
3 * Copyright NumFOCUS
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0.txt
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *=========================================================================*/
18#ifndef itkQuadEdgeMeshDecimationQuadricElementHelper_h
19#define itkQuadEdgeMeshDecimationQuadricElementHelper_h
20
21#include "itkPoint.h"
22#include "vnl/vnl_vector_fixed.h"
23#include "vnl/vnl_matrix.h"
24#include "vnl/algo/vnl_matrix_inverse.h"
25
26#include "itkTriangleHelper.h"
27
28namespace itk
29{
31template <typename TPoint>
33{
34public:
36 using PointType = TPoint;
37 using CoordType = typename PointType::CoordinateType;
38
39 static constexpr unsigned int PointDimension = PointType::PointDimension;
40 static constexpr unsigned int NumberOfCoefficients = PointDimension * (PointDimension + 1 / 2 + PointDimension + 1);
41
43 using VNLMatrixType = vnl_matrix<CoordType>;
44 using VNLVectorType = vnl_vector_fixed<CoordType, Self::PointDimension>;
45 using CoefficientVectorType = vnl_vector_fixed<CoordType, Self::NumberOfCoefficients>;
47
48 // *****************************************************************
52 , m_B(CoordType{})
53 , m_SVDAbsoluteThreshold(static_cast<CoordType>(1e-6))
54 , m_SVDRelativeThreshold(static_cast<CoordType>(1e-3))
55 {
56 this->m_Rank = PointDimension;
57 }
58
60 : m_Coefficients(iCoefficients)
62 , m_B(CoordType{})
63 , m_SVDAbsoluteThreshold(static_cast<CoordType>(1e-3))
64 , m_SVDRelativeThreshold(static_cast<CoordType>(1e-3))
65 {
66 this->m_Rank = PointDimension;
68 }
69
71
74 {
75 return this->m_Coefficients;
76 }
77
80 {
82 return m_A;
83 }
84
87 {
89 return m_B;
90 }
91
92 unsigned int
93 GetRank() const
94 {
95 return m_Rank;
96 }
97
99 inline CoordType
100 ComputeError(const PointType & iP) const
101 {
102 // ComputeAMatrixAndBVector();
103 vnl_svd<CoordType> svd(m_A, m_SVDAbsoluteThreshold);
104 svd.zero_out_relative(m_SVDRelativeThreshold);
105 const CoordType oError = inner_product(iP.GetVnlVector(), svd.recompose() * iP.GetVnlVector());
106
107 return this->m_Coefficients.back() - oError;
108 /*
109 CoordType oError( 0. );
110
111 std::vector< CoordType > pt( PointDimension + 1, 1. );
112
113 unsigned int dim1( 0 ), dim2, k( 0 );
114
115 while( dim1 < PointDimension )
116 {
117 pt[dim1] = iP[dim1];
118 ++dim1;
119 }
120
121 for( dim1 = 0; dim1 < PointDimension + 1; ++dim1 )
122 {
123 oError += this->m_Coefficients[k++] * pt[dim1] * pt[dim1];
124
125 for( dim2 = dim1 + 1; dim2 < PointDimension + 1; ++dim2 )
126 {
127 oError += 2. * this->m_Coefficients[k++] * pt[dim1] * pt[dim2];
128 }
129 }
130 oError += this->m_Coefficients[k++];
131
132 return oError;*/
133 }
134
136 inline CoordType
138 {
139 PointType optimal_location = ComputeOptimalLocation(iP);
140
141 return ComputeError(optimal_location);
142 }
143
146 {
148
149 vnl_svd<CoordType> svd(m_A, m_SVDAbsoluteThreshold);
150 svd.zero_out_relative(m_SVDRelativeThreshold);
151
152 m_Rank = svd.rank();
153
154 const auto y = (m_B.as_vector() - m_A * iP.GetVnlVector());
155
156 VNLVectorType displacement = svd.solve(y);
157
158 PointType oP;
159 for (unsigned int dim = 0; dim < PointDimension; ++dim)
160 {
161 oP[dim] = iP[dim] + displacement[dim];
162 }
163 return oP;
164 }
165
168 ComputeOptimalLocation(const unsigned int)
169 {}
170
171 void
173 const PointType & iP2,
174 const PointType & iP3,
175 const CoordType & iWeight = static_cast<CoordType>(1.))
176 {
177 const VectorType N = TriangleType::ComputeNormal(iP1, iP2, iP3);
178
179 AddPoint(iP1, N, iWeight);
180 }
181
182 void
183 AddPoint(const PointType & iP, const VectorType & iN, const CoordType & iWeight = static_cast<CoordType>(1.))
184 {
185 unsigned int k(0); /*one-line-declaration*/
186 const CoordType d = -iN * iP.GetVectorFromOrigin();
187 for (unsigned int dim1 = 0; dim1 < PointDimension; ++dim1)
188 {
189 for (unsigned int dim2 = dim1; dim2 < PointDimension; ++dim2)
190 {
191 this->m_Coefficients[k++] += iWeight * iN[dim1] * iN[dim2];
192 }
193 this->m_Coefficients[k++] += iWeight * iN[dim1] * d;
194 }
195
196 this->m_Coefficients[k++] += iWeight * d * d;
197 }
198
199 // ***********************************************************************
200 // operators
201 Self &
202 operator=(const Self & iRight)
203 {
204 if (this != &iRight)
205 {
206 this->m_Coefficients = iRight.m_Coefficients;
207 }
208 return *this;
209 }
210
211 Self
212 operator+(const Self & iRight) const
213 {
214 return Self(this->m_Coefficients + iRight.m_Coefficients);
215 }
216
217 Self &
218 operator+=(const Self & iRight)
219 {
220 this->m_Coefficients += iRight.m_Coefficients;
221 return *this;
222 }
223
224 Self
225 operator-(const Self & iRight) const
226 {
227 return Self(this->m_Coefficients - iRight.m_Coefficients);
228 }
229
230 Self &
231 operator-=(const Self & iRight)
232 {
233 this->m_Coefficients -= iRight.m_Coefficients;
234 return *this;
235 }
236
237 Self
238 operator*(const CoordType & iV) const
239 {
240 Self oElement(this->m_Coefficients * iV);
241
242 return oElement;
243 }
244
245 Self &
247 {
248 this->m_Coefficients *= iV;
249 return *this;
250 }
251
252protected:
256 unsigned int m_Rank;
259 // bool m_MatrixFilled;
260
261 void
263 {
264 unsigned int k(0);
265 for (unsigned int dim1 = 0; dim1 < PointDimension; ++dim1)
266 {
267 for (unsigned int dim2 = dim1; dim2 < PointDimension; ++dim2)
268 {
269 m_A[dim1][dim2] = m_A[dim2][dim1] = m_Coefficients[k++];
270 }
271 m_B[dim1] = -m_Coefficients[k++];
272 }
273 // m_MatrixFilled = true;
274 }
275};
276} // namespace itk
277#endif
Pixel-wise addition of two images.
vnl_vector_fixed< CoordType, Self::PointDimension > VNLVectorType
PointType ComputeOptimalLocation(const unsigned int)
TODO to be implemented!!!
CoordType ComputeErrorAtOptimalLocation(const PointType &iP)
TODO this method should be really optimized!!!
CoordType ComputeError(const PointType &iP) const
TODO this method should be really optimized!!!
vnl_vector_fixed< CoordType, Self::NumberOfCoefficients > CoefficientVectorType
QuadEdgeMeshDecimationQuadricElementHelper(const CoefficientVectorType &iCoefficients)
void AddPoint(const PointType &iP, const VectorType &iN, const CoordType &iWeight=static_cast< CoordType >(1.))
void AddTriangle(const PointType &iP1, const PointType &iP2, const PointType &iP3, const CoordType &iWeight=static_cast< CoordType >(1.))
A convenience class for computation of various triangle elements in 2D or 3D.
static VectorType ComputeNormal(const PointType &iA, const PointType &iB, const PointType &iC)
Compute Normal vector to the triangle formed by (iA,iB,iC)
static constexpr double e
Definition: itkMath.h:56
The "itk" namespace contains all Insight Segmentation and Registration Toolkit (ITK) classes....