Shapeworks Studio  2.1
Shape analysis software suite
itkPSMImplicitSurfaceDomain.hxx
1 /*=========================================================================
2  *
3  * Copyright Insight Software Consortium
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  * http://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 __itkPSMImplicitSurfaceDomain_hxx
19 #define __itkPSMImplicitSurfaceDomain_hxx
20 #include "itkPSMImplicitSurfaceDomain.h"
21 
22 #include "vnl/vnl_math.h"
23 #include "vnl/vnl_cross.h"
24 
25 namespace itk
26 {
27 
28 template<class T, unsigned int VDimension>
29 void
30 PSMImplicitSurfaceDomain<T, VDimension>::
31 SetCuttingPlane(const vnl_vector<double> &a, const vnl_vector<double> &b,
32  const vnl_vector<double> &c)
33 {
34  // See http://mathworld.wolfram.com/Plane.html, for example
35  vnl_vector<double> q;
36  if (VDimension == 3) q = vnl_cross_3d((b-a),(c-a));
37  else if (VDimension == 2) q = vnl_cross_2d((b-a),(c-a));
38 
39  if (q.magnitude() > 0.0)
40  {
41  m_CuttingPlaneNormal = q / q.magnitude();
42  m_CuttingPlanePoint = a;
43  m_UseCuttingPlane = true;
44  }
45 }
46 
47 template<class T, unsigned int VDimension>
48 bool
50 ApplyVectorConstraints(vnl_vector_fixed<double, VDimension> &gradE,
51  const PointType &pos,
52  double maxtimestep) const
53 {
54  if (this->m_UseCuttingPlane == true)
55  {
56  // See http://mathworld.wolfram.com/Point-PlaneDistance.html, for example
57  vnl_vector_fixed<double, VDimension> x;
58  vnl_vector_fixed<T, VDimension> grad = this->SampleGradientVnl(pos);
59  for (unsigned int i = 0; i < VDimension; i++)
60  { x[i] = pos[i]; }
61  const double D = dot_product(m_CuttingPlaneNormal, x- m_CuttingPlanePoint);
62 
63  // x = m_CuttingPlaneNormal * fabs(1.0 / (D + 1.0e-3));
64  // x = m_CuttingPlaneNormal * lambda * exp(-lambda * fabs(D));
65 
66  // Gradient of simple force 1/D^2 to push away from cutting plane
67  vnl_vector_fixed<double, VDimension> df;
68  const double k = (-2.0 / (D * D * D));
69  df[0] = k * grad[0] * m_CuttingPlaneNormal[0];
70  df[1] = k * grad[1] * m_CuttingPlaneNormal[1];
71  df[2] = k * grad[2] * m_CuttingPlaneNormal[2];
72 
73  gradE = gradE + df;
74 
75  // Make sure force is not huge relative to other forces.
76  if (gradE.magnitude() > maxtimestep)
77  {
78  gradE.normalize();
79  gradE = gradE * maxtimestep;
80  }
81  }
82 
83 
84  return Superclass::ApplyVectorConstraints(gradE,pos,maxtimestep);
85 }
86 
87 template<class T, unsigned int VDimension>
88 bool
90 {
91  // First apply and constraints imposed by superclasses. This will
92  // guarantee the point starts in the correct image domain.
93  bool flag = Superclass::ApplyConstraints(p);
94 
95  if (this->m_ConstraintsEnabled == true)
96  {
97 
98  unsigned int k = 0;
99  double mult = 1.0;
100 
101  const T epsilon = m_Tolerance * 0.001;
102  T f = this->Sample(p);
103 
104  T gradmag = 1.0;
105  while ( fabs(f) > (m_Tolerance * mult) || gradmag < epsilon)
106  // while ( fabs(f) > m_Tolerance || gradmag < epsilon)
107  {
108  vnl_vector_fixed<T, VDimension> grad = this->SampleGradientVnl(p);
109 
110  gradmag = grad.magnitude();
111  vnl_vector_fixed<T, VDimension> vec = grad * ( f / (gradmag + epsilon) );
112  for (unsigned int i = 0; i < VDimension; i++)
113  {
114  p[i] -= vec[i];
115  }
116 
117  f = this->Sample(p);
118 
119  // Raise the tolerance if we have done too many iterations.
120  k++;
121  if (k > 10000)
122  {
123  mult *= 2.0;
124  k = 0;
125  }
126  } // end while
127  } // end if m_ConstraintsEnabled == true
128 
129  return flag;
130 }
131 
132 template <class T, unsigned int VDimension>
133 double
135 {
136  double sum = 0.0;
137  for (unsigned int i = 0; i < VDimension; i++)
138  { sum += (b[i]-a[i]) * (b[i]-a[i]); }
139  return sqrt(sum);
140 }
141 
142 } // end namespace
143 #endif
virtual bool ApplyVectorConstraints(vnl_vector_fixed< double, VDimension > &gradE, const PointType &pos, double maxtimestep) const
virtual double Distance(const PointType &, const PointType &) const
virtual bool ApplyConstraints(PointType &p) const