1 #include <iostream>
2 #include <cmath>
3 #include "boxm2_vecf_mandible.h"
4 #include <bvrml/bvrml_write.h>
5 #include "vgl/vgl_intersection.h"
6 #include "vgl/vgl_box_3d.h"
7 #include "vgl/vgl_bounding_box.h"
8 #ifdef _MSC_VER
9 #  include "vcl_msvc_warnings.h"
10 #endif
11 #include "vnl/vnl_vector_fixed.h"
12 #include "vnl/vnl_quaternion.h"
13 
14 //==========================================
15 //: mandible class member implementations
fill_boundary_map()16 void boxm2_vecf_mandible::fill_boundary_map(){
17   boundary_knots_["right_ramus_end"] = 44;
18   boundary_knots_["right_angle_center"] = 35;
19   boundary_knots_["right_body_end"] = 34;
20   boundary_knots_["mid_jaw"] = 21;
21   boundary_knots_["left_body_start"] = 10;
22   boundary_knots_["left_angle_center"] =9 ;
23   boundary_knots_["left_ramus_start"] = 0;
24 }
25 
set_inv_rot()26 void boxm2_vecf_mandible::set_inv_rot(){
27   // set rotation from params
28   vnl_vector_fixed<double,3> X(1.0, 0.0, 0.0);
29   vnl_quaternion<double> Q(X,params_.jaw_opening_angle_rad_);
30   vgl_rotation_3d<double> rot(Q);
31   inv_rot_ = rot.inverse();
32 }
33 
boxm2_vecf_mandible(std::string const & geometry_file)34 boxm2_vecf_mandible::boxm2_vecf_mandible(std::string const& geometry_file){
35   std::ifstream istr(geometry_file.c_str());
36   if(!istr){
37     std::cout << " invalid path for manidble geometry " << geometry_file << '\n';
38     fill_boundary_map();
39     return;
40   }
41   std::map<std::string, std::string> mandible_paths;
42   std::string component, path;
43   while(istr >> component >> path)
44     mandible_paths[component] = path;
45   std::map<std::string, std::string>::iterator pit;
46   pit = mandible_paths.find("axis_spline");
47   if(pit != mandible_paths.end()){
48     std::ifstream sstr((pit->second).c_str());
49     this->read_axis_spline(sstr);
50   }
51   pit = mandible_paths.find("cross_section_pointset");
52   if(pit != mandible_paths.end()){
53       std::ifstream cstr((pit->second).c_str());
54       this->load_cross_section_pointsets(cstr);
55   }
56   this->set_inv_rot();
57 }
translate(vgl_vector_3d<double> const & tr)58 boxm2_vecf_spline_field boxm2_vecf_mandible::translate(vgl_vector_3d<double> const& tr){
59   std::vector<vgl_point_3d<double> > knots = axis_.knots();
60   std::vector<vgl_vector_3d<double> > ret(axis_.n_knots(), tr);
61   boxm2_vecf_spline_field field(axis_, ret);
62   return field;
63 }
64 
65 // adjust the x coordinates with respect to the symmetry plane
offset_axis(double offset)66 boxm2_vecf_spline_field boxm2_vecf_mandible::offset_axis(double offset) {
67   std::vector<vgl_point_3d<double> > knots = axis_.knots();
68   std::vector<vgl_vector_3d<double> > ret;
69   for(unsigned i = 0; i<axis_.n_knots(); ++i){
70     vgl_point_3d<double> p = knots[i];
71     // the tangent unit vector to the curve at knot i
72     auto t = static_cast<double>(i);
73     vgl_vector_3d<double> dpdt = axis_.tangent(t);
74     dpdt /= dpdt.length();
75     // the normal to the curve in the X-Z plane
76     vgl_vector_3d<double> unit_y(0.0, 1.0, 0.0);
77     vgl_vector_3d<double> curve_normal = cross_product(unit_y,dpdt);
78     curve_normal/=curve_normal.length();
79     vgl_vector_3d<double> motion = curve_normal*offset;
80     ret.push_back(motion);
81   }
82   boxm2_vecf_spline_field field(axis_, ret);
83   return field;
84 }
85 
tilt_ramus(double delta_z_at_condyle)86 boxm2_vecf_spline_field boxm2_vecf_mandible::tilt_ramus(double delta_z_at_condyle){
87   std::vector<vgl_point_3d<double> > knots = axis_.knots();
88   std::vector<vgl_vector_3d<double> > ret;
89   for(unsigned i = 0; i<axis_.n_knots(); ++i){
90     vgl_point_3d<double> p = knots[i];
91     auto t = static_cast<double>(i);
92     bool is_right = p.x()<0.0;
93     double dz = 0.0;
94     if(is_right){
95       double tstart = static_cast<double>(boundary_knots_["right_ramus_end"]);
96       double tend = static_cast<double>(boundary_knots_["right_angle_center"]);
97       dz = (tend-t)/(tend-tstart);
98       dz *= delta_z_at_condyle;
99     }else{
100       double tstart = static_cast<double>(boundary_knots_["left_ramus_end"]);
101       double tend = static_cast<double>(boundary_knots_["left_angle_center"]);
102       dz = (tend-t)/(tend-tstart);
103       dz *= delta_z_at_condyle;
104     }
105     if(dz<0.0) dz = 0.0;
106     // the tangent unit vector to the curve at knot i
107     vgl_vector_3d<double> dpdt = axis_.tangent(t);
108     dpdt /= dpdt.length();
109 
110     vgl_vector_3d<double> unit_x(1.0, 0.0, 0.0), unit_z(0.0, 0.0, 1.0);
111     if(is_right)
112       unit_x *= -1.0;
113     vgl_vector_3d<double> curve_normal = cross_product(dpdt,unit_x);
114     curve_normal/=curve_normal.length();
115 
116     vgl_vector_3d<double> motion = curve_normal*dz/std::fabs(dot_product(curve_normal, unit_z));
117     ret.push_back(motion);
118   }
119   boxm2_vecf_spline_field field(axis_, ret);
120   return field;
121 }
122 
tilt_body(double delta_y_at_chin)123 boxm2_vecf_spline_field  boxm2_vecf_mandible::tilt_body(double delta_y_at_chin) {
124   std::vector<vgl_point_3d<double> > knots = axis_.knots();
125   std::vector<vgl_vector_3d<double> > ret;
126   for(unsigned i = 0; i<axis_.n_knots(); ++i){
127     vgl_point_3d<double> p = knots[i];
128     auto t = static_cast<double>(i);
129     double dy = 0.0;
130     bool is_right = p.x()<0.0;
131     // find the magnitude of the motion vector, which falls off linearly from the chin
132     // domain body for either left or right of the symmetry plane
133     if(is_right){
134       double tstart = static_cast<double>(boundary_knots_["mid_jaw"]);
135       double tend = static_cast<double>(boundary_knots_["right_angle_center"]);
136       dy = (tend-t)/(tend-tstart);
137       dy *= delta_y_at_chin;
138     }else{
139       double tstart = static_cast<double>(boundary_knots_["mid_jaw"]);
140       double tend = static_cast<double>(boundary_knots_["left_angle_center"]);
141       dy = (tend-t)/(tend-tstart);
142       dy *= delta_y_at_chin;
143     }
144     // turn off the motion at the boundary of body and angle
145     if(dy<0.0) dy = 0.0;
146     // the tangent unit vector to the curve at knot i
147     vgl_vector_3d<double> dpdt = axis_.tangent(t);
148     dpdt /= dpdt.length();
149     vgl_vector_3d<double> unit_x(1.0, 0.0, 0.0), unit_y(0.0, 1.0, 0.0), unit_z(0.0, 0.0, 1.0), motion;
150 
151     // determine which orientation the curve normal should have and then compute the motion normal to the curve
152     // to achieve the required dy
153     double dp_x = dot_product(dpdt, unit_x), dp_z = dot_product(dpdt, unit_z);
154     if(std::fabs(dp_x)>std::fabs(dp_z)){
155     vgl_vector_3d<double> curve_normal = cross_product(dpdt,unit_z);
156     curve_normal/=curve_normal.length();
157     motion= curve_normal*dy/std::fabs(dot_product(curve_normal, unit_y));
158     }else{
159       if(is_right)
160         unit_x *= -1.0;
161       vgl_vector_3d<double> curve_normal = cross_product(dpdt,unit_x);
162       curve_normal/=curve_normal.length();
163       motion= curve_normal*dy/std::fabs(dot_product(curve_normal, unit_y));
164     }
165     ret.push_back(motion);
166   }
167   boxm2_vecf_spline_field field(axis_, ret);
168   return field;
169 }
170 
apply_vector_field(boxm2_vecf_spline_field const & field) const171 boxm2_vecf_mandible boxm2_vecf_mandible::apply_vector_field(boxm2_vecf_spline_field const& field) const{
172   // transform self's spline
173   vgl_cubic_spline_3d<double> axis_v = field.apply_field();
174   std::vector<bvgl_cross_section> csects_v;
175   for(const auto & cross_section : cross_sections_){
176     double t = cross_section.t();
177     vgl_vector_3d<double> v = field(t);
178     bvgl_cross_section csv = cross_section.apply_vector(v);
179     csects_v.push_back(csv);
180   }
181   return boxm2_vecf_mandible(boundary_knots_, axis_v, csects_v);
182 }
183 
display_axis_spline(std::ofstream & ostr) const184 void boxm2_vecf_mandible::display_axis_spline(std::ofstream& ostr) const{
185   bvrml_write::write_vrml_header(ostr);
186   // display the knots
187   std::vector<vgl_point_3d<double> > knots = axis_.knots();
188   auto n = static_cast<unsigned>(knots.size());
189   auto nd = static_cast<double>(n-1);
190   float r = 1.0f;
191   for(unsigned i =0; i<n; ++i){
192     vgl_point_3d<double> p = knots[i];
193     vgl_point_3d<float> pf(static_cast<float>(p.x()), static_cast<float>(p.y()), static_cast<float>(p.z()));
194     vgl_sphere_3d<float> sp(pf, r);
195     bool found = false;
196     for(auto bit =  boundary_knots_.begin();
197         bit != boundary_knots_.end()&&!found;++bit)
198       found = bit->second == i;
199     if(found)
200       bvrml_write::write_vrml_sphere(ostr, sp, 1.0f, 0.0f, 1.0f);
201     else
202       bvrml_write::write_vrml_sphere(ostr, sp, 0.0f, 1.0f, 0.0f);
203   }
204   // display the spline points
205   for(double t = 0; t<=nd; t+=0.05){
206     vgl_point_3d<double> p = axis_(t);
207     vgl_point_3d<float> pf(static_cast<float>(p.x()), static_cast<float>(p.y()), static_cast<float>(p.z()));
208     vgl_sphere_3d<float> sp(pf, 0.25f);
209     bvrml_write::write_vrml_sphere(ostr, sp, 1.0f, 1.0f, 0.0f);
210   }
211   ostr.close();
212 }
213 // assume no jaw deformations for now,just jaw rotation
inverse_vector_field(vgl_point_3d<double> const & target_pt,vgl_vector_3d<double> & inv_vf) const214 bool boxm2_vecf_mandible::inverse_vector_field(vgl_point_3d<double> const& target_pt, vgl_vector_3d<double>& inv_vf) const{
215   vgl_point_3d<double> p = target_pt-params_.offset_;
216   vgl_point_3d<double> rp = inv_rot_ * p;// rotated point
217   inv_vf.set(rp.x() - target_pt.x(), rp.y() - target_pt.y(), rp.z() - target_pt.z());
218   return true;
219 }
220