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