Alternaria
fit cylinders and ellipsoids to fungus
|
00001 /* 00002 * This work is licensed under a Creative Commons 00003 * Attribution-Noncommercial-Share Alike 3.0 United States License. 00004 * 00005 * http://creativecommons.org/licenses/by-nc-sa/3.0/us/ 00006 * 00007 * You are free: 00008 * 00009 * to Share - to copy, distribute, display, and perform the work 00010 * to Remix - to make derivative works 00011 * 00012 * Under the following conditions: 00013 * 00014 * Attribution. You must attribute the work in the manner specified by the 00015 * author or licensor (but not in any way that suggests that they endorse you 00016 * or your use of the work). 00017 * 00018 * Noncommercial. You may not use this work for commercial purposes. 00019 * 00020 * Share Alike. If you alter, transform, or build upon this work, you may 00021 * distribute the resulting work only under the same or similar license to 00022 * this one. 00023 * 00024 * For any reuse or distribution, you must make clear to others the license 00025 * terms of this work. The best way to do this is by including this header. 00026 * 00027 * Any of the above conditions can be waived if you get permission from the 00028 * copyright holder. 00029 * 00030 * Apart from the remix rights granted under this license, nothing in this 00031 * license impairs or restricts the author's moral rights. 00032 */ 00033 00034 00046 #include <config.h> 00047 00048 #if defined ALTERNARIA_HAVE_OPENGL_FRAMEWORK 00049 #include <OpenGL/gl.h> 00050 #include <OpenGL/glu.h> 00051 #elif defined ALTERNARIA_HAVE_OPENGL 00052 #include <GL/gl.h> 00053 #include <GL/glu.h> 00054 #endif 00055 00056 #include <cstring> 00057 #include <cmath> 00058 #include <cctype> 00059 #include <cassert> 00060 #include <list> 00061 #include <vector> 00062 #include <iostream> 00063 #include <iomanip> 00064 #include <sstream> 00065 00066 #include <inttypes.h> 00067 00068 #include <jwsc/base/limits.h> 00069 #include <jwsc/math/constants.h> 00070 #include <jwsc/prob/pdf.h> 00071 #include <jwsc/vector/vector.h> 00072 #include <jwsc/vector/vector_math.h> 00073 #include <jwsc/matrix/matrix.h> 00074 #include <jwsc/matrix/matrix_math.h> 00075 #include <jwsc/matblock/matblock.h> 00076 00077 #include <jwsc++/base/exception.h> 00078 00079 #include "density.h" 00080 #include "printable.h" 00081 #include "structure.h" 00082 00083 00084 using std::list; 00085 using std::vector; 00086 using std::ios_base; 00087 using std::istream; 00088 using std::ostringstream; 00089 using std::istringstream; 00090 using std::streampos; 00091 using std::isspace; 00092 using namespace jwsc; 00093 using jwscxx::base::Arg_error; 00094 using jwscxx::base::Result_error; 00095 using jwscxx::base::IO_error; 00096 00097 00098 /* ------------------------- Structure_density ---------------------------- */ 00099 00106 void Structure_density::set_centroid_x(float min, float max) throw (Arg_error) 00107 { 00108 centroid_x.set(min, max); 00109 } 00110 00111 00118 void Structure_density::set_centroid_y(float min, float max) throw (Arg_error) 00119 { 00120 centroid_y.set(min, max); 00121 } 00122 00123 00130 void Structure_density::set_centroid_z(float min, float max) throw (Arg_error) 00131 { 00132 centroid_z.set(min, max); 00133 } 00134 00135 00145 void Structure_density::set_length 00146 ( 00147 float mu, 00148 float sigma, 00149 float min, 00150 float max 00151 ) 00152 throw (Arg_error) 00153 { 00154 if (min < 0) 00155 { 00156 throw Arg_error("Minimum must be >= 0"); 00157 } 00158 length.set(mu, sigma, min, max); 00159 } 00160 00161 00171 void Structure_density::set_width 00172 ( 00173 float mu, 00174 float sigma, 00175 float min, 00176 float max 00177 ) 00178 throw (Arg_error) 00179 { 00180 if (min < 0) 00181 { 00182 throw Arg_error("Minimum must be >= 0"); 00183 } 00184 width.set(mu, sigma, min, max); 00185 } 00186 00187 00197 void Structure_density::set_theta 00198 ( 00199 float mu, 00200 float sigma, 00201 float min, 00202 float max 00203 ) 00204 throw (Arg_error) 00205 { 00206 if (min < 0) 00207 { 00208 throw Arg_error("Minimum must be >= 0"); 00209 } 00210 if (max > JWSC_PI) 00211 { 00212 throw Arg_error("Maximum must be <= PI"); 00213 } 00214 theta.set(mu, sigma, min, max); 00215 } 00216 00217 00224 void Structure_density::set_psi(float min, float max) throw (Arg_error) 00225 { 00226 if (min < -JWSC_PI) 00227 { 00228 throw Arg_error("Minimum must be >= PI"); 00229 } 00230 if (max > JWSC_PI) 00231 { 00232 throw Arg_error("Maximum must be <= PI"); 00233 } 00234 psi.set(min, max); 00235 } 00236 00237 00247 void Structure_density::set_opacity 00248 ( 00249 float mu, 00250 float sigma, 00251 float min, 00252 float max 00253 ) 00254 throw (Arg_error) 00255 { 00256 if (min < 0 || max > 1) 00257 { 00258 throw Arg_error("Parameter range must be in [0,1]"); 00259 } 00260 opacity.set(mu, sigma, min, max); 00261 } 00262 00263 00265 float Structure_density::sample_centroid_x() const 00266 { 00267 return (float)sample_uniform_pdf_d(centroid_x.get_min(), 00268 centroid_x.get_max()); 00269 } 00270 00271 00273 float Structure_density::sample_centroid_y() const 00274 { 00275 return (float)sample_uniform_pdf_d(centroid_y.get_min(), 00276 centroid_y.get_max()); 00277 } 00278 00279 00281 float Structure_density::sample_centroid_z() const 00282 { 00283 return (float)sample_uniform_pdf_d(centroid_z.get_min(), 00284 centroid_z.get_max()); 00285 } 00286 00287 00289 float Structure_density::sample_length() const 00290 { 00291 return (float)sample_gaussian_pdf_d(length.get_mu(), length.get_sigma(), 00292 length.get_min(), length.get_max()); 00293 } 00294 00295 00297 float Structure_density::sample_width() const 00298 { 00299 return (float)sample_gaussian_pdf_d(width.get_mu(), width.get_sigma(), 00300 width.get_min(), width.get_max()); 00301 } 00302 00303 00305 float Structure_density::sample_theta() const 00306 { 00307 return (float)sample_gaussian_pdf_d(theta.get_mu(), 00308 theta.get_sigma(), theta.get_min(), theta.get_max()); 00309 } 00310 00311 00313 float Structure_density::sample_psi() const 00314 { 00315 return (float)sample_uniform_pdf_d(psi.get_min(), psi.get_max()); 00316 } 00317 00318 00320 float Structure_density::sample_opacity() const 00321 { 00322 return (float)sample_gaussian_pdf_d(opacity.get_mu(), 00323 opacity.get_sigma(), opacity.get_min(), opacity.get_max()); 00324 } 00325 00326 /* -------------------------------------------------------------------------- */ 00327 00328 00329 00330 00331 00332 00333 00334 00335 00336 /* ------------------------- Lateral_structure_density -------------------- */ 00337 00347 void Lateral_structure_density::set_lat_dist 00348 ( 00349 float mu, 00350 float sigma, 00351 float min, 00352 float max 00353 ) 00354 throw (Arg_error) 00355 { 00356 if (min < 0 || max > 1) 00357 { 00358 throw Arg_error("Parameter range must be in [0,1]"); 00359 } 00360 lat_dist.set(mu, sigma, min, max); 00361 } 00362 00363 00365 float Lateral_structure_density::sample_lat_dist() const 00366 { 00367 return (float)sample_gaussian_pdf_d(lat_dist.get_mu(), 00368 lat_dist.get_sigma(), lat_dist.get_min(), lat_dist.get_max()); 00369 } 00370 00371 /* -------------------------------------------------------------------------- */ 00372 00373 00374 00375 00376 00377 00378 00379 /* ------------------------------ Structure ------------------------------- */ 00380 00395 Structure::Structure 00396 ( 00397 float length, 00398 float width, 00399 float base_theta, 00400 float base_psi, 00401 float theta, 00402 float psi, 00403 float opacity, 00404 size_t level, 00405 const class Structure_density* density 00406 ) 00407 throw (Arg_error) 00408 : laterals() 00409 { 00410 this->length = length; 00411 this->width = width; 00412 this->base_theta = base_theta; 00413 this->base_psi = base_psi; 00414 this->theta = theta; 00415 this->psi = psi; 00416 this->opacity = opacity; 00417 this->level = level; 00418 this->density = density; 00419 00420 check_length(); 00421 check_width(); 00422 check_base_theta(); 00423 check_base_psi(); 00424 check_theta(); 00425 check_psi(); 00426 check_opacity(); 00427 00428 parent = 0; 00429 apical = 0; 00430 begin_pt = 0; 00431 end_pt = 0; 00432 growth_dir = 0; 00433 centroid = 0; 00434 R = 0; 00435 log_prob = 0; 00436 log_prob_descend = 0; 00437 00438 id = generate_id(); 00439 } 00440 00441 00443 Structure::Structure(const Structure& s) : laterals(s.laterals) 00444 { 00445 id = s.id; 00446 level = s.level; 00447 length = s.length; 00448 width = s.width; 00449 base_theta = s.base_theta; 00450 base_psi = s.base_psi; 00451 theta = s.theta; 00452 psi = s.psi; 00453 opacity = s.opacity; 00454 density = s.density; 00455 parent = s.parent; 00456 apical = s.apical; 00457 00458 begin_pt = 0; 00459 copy_vector_f(&begin_pt, s.begin_pt); 00460 00461 end_pt = 0; 00462 copy_vector_f(&end_pt, s.end_pt); 00463 00464 growth_dir = 0; 00465 copy_vector_f(&growth_dir, s.growth_dir); 00466 00467 centroid = 0; 00468 copy_vector_f(¢roid, s.centroid); 00469 00470 R = 0; 00471 copy_matrix_f(&R, s.R); 00472 00473 log_prob = s.log_prob; 00474 log_prob_descend = s.log_prob_descend; 00475 } 00476 00477 00479 Structure::~Structure() 00480 { 00481 free_vector_f(begin_pt); 00482 free_vector_f(end_pt); 00483 free_vector_f(centroid); 00484 free_matrix_f(R); 00485 free_vector_f(growth_dir); 00486 00487 delete apical; 00488 00489 for (list<Lateral_structure*>::iterator it = laterals.begin(); 00490 it != laterals.end(); it++) 00491 { 00492 delete *it; 00493 } 00494 } 00495 00496 00502 Structure& Structure::operator= (const Structure& s) 00503 { 00504 id = s.id; 00505 level = s.level; 00506 length = s.length; 00507 width = s.width; 00508 base_theta = s.base_theta; 00509 base_psi = s.base_psi; 00510 theta = s.theta; 00511 psi = s.psi; 00512 opacity = s.opacity; 00513 density = s.density; 00514 parent = s.parent; 00515 apical = s.apical; 00516 00517 laterals.clear(); 00518 laterals = s.laterals; 00519 00520 copy_vector_f(&begin_pt, s.begin_pt); 00521 00522 copy_vector_f(&end_pt, s.end_pt); 00523 00524 copy_vector_f(&growth_dir, s.growth_dir); 00525 00526 copy_vector_f(¢roid, s.centroid); 00527 00528 copy_matrix_f(&R, s.R); 00529 00530 log_prob = s.log_prob; 00531 log_prob_descend = s.log_prob_descend; 00532 00533 return *this; 00534 } 00535 00536 00538 Structure* Structure::get_root() 00539 { 00540 if (parent) 00541 return parent->get_root(); 00542 00543 return this; 00544 } 00545 00546 00548 vector<Structure*>* Structure::get_descendants() 00549 { 00550 list<Structure*>* descendants = new list<Structure*>(); 00551 descendants->push_back(this); 00552 00553 if (apical) 00554 { 00555 vector<Structure*>* apical_descend = apical->get_descendants(); 00556 descendants->insert(descendants->end(), apical_descend->begin(), 00557 apical_descend->end()); 00558 delete apical_descend; 00559 } 00560 for (list<Lateral_structure*>::const_iterator it = laterals.begin(); 00561 it != laterals.end(); it++) 00562 { 00563 vector<Structure*>* lateral_descend = (*it)->get_descendants(); 00564 descendants->insert(descendants->end(), lateral_descend->begin(), 00565 lateral_descend->end()); 00566 delete lateral_descend; 00567 } 00568 00569 vector<Structure*>* descendants_v = new vector<Structure*>( 00570 descendants->begin(), descendants->end()); 00571 delete descendants; 00572 00573 return descendants_v; 00574 } 00575 00576 00578 void Structure::remove_lateral(class Lateral_structure* s) throw (Arg_error) 00579 { 00580 for (list<Lateral_structure*>::iterator it = laterals.begin(); 00581 it != laterals.end(); it++) 00582 { 00583 if ((*it) == s) 00584 { 00585 laterals.erase(it); 00586 update_ancestry_log_prob(); 00587 return; 00588 } 00589 } 00590 00591 throw Arg_error("Could not find lateral to remove"); 00592 } 00593 00594 00605 void Structure::set_length(float length) throw (Arg_error) 00606 { 00607 set_size(length, width); 00608 } 00609 00610 00618 void Structure::set_width(float width) throw (Arg_error) 00619 { 00620 set_size(length, width); 00621 } 00622 00623 00635 void Structure::set_size(float length, float width) throw (Arg_error) 00636 { 00637 static int entry = 0; 00638 00639 entry++; 00640 00641 float old_length = this->length; 00642 float old_width = this->width; 00643 00644 try 00645 { 00646 this->length = length; 00647 check_length(); 00648 00649 this->width = width; 00650 check_width(); 00651 00652 update_centroid(); 00653 update_end_pt(); 00654 update_apical(); 00655 update_laterals(); 00656 update_ancestry_log_prob(); 00657 } 00658 catch (Arg_error e) 00659 { 00660 if (entry < 2) 00661 { 00662 set_size(old_length, old_width); 00663 } 00664 else 00665 { 00666 // TODO the length has been coming up wrong because of precision. 00667 // Probably could throw something like Result_error exception 00668 // here. 00669 entry = 0; 00670 } 00671 throw e; 00672 } 00673 } 00674 00675 00683 void Structure::set_theta(float theta) throw (Arg_error) 00684 { 00685 set_orientation(theta, psi); 00686 } 00687 00688 00696 void Structure::set_base_theta(float base_theta) throw (Arg_error) 00697 { 00698 set_base_orientation(base_theta, base_psi); 00699 } 00700 00701 00709 void Structure::set_psi(float psi) throw (Arg_error) 00710 { 00711 set_orientation(theta, psi); 00712 } 00713 00714 00722 void Structure::set_base_psi(float base_psi) throw (Arg_error) 00723 { 00724 set_base_orientation(base_theta, base_psi); 00725 } 00726 00727 00736 void Structure::set_orientation(float theta, float psi) throw (Arg_error) 00737 { 00738 static int entry = 0; 00739 00740 entry++; 00741 00742 float old_theta = this->theta; 00743 float old_psi = this->psi; 00744 00745 try 00746 { 00747 this->theta = theta; 00748 check_theta(); 00749 00750 this->psi = psi; 00751 check_psi(); 00752 00753 update_R(); 00754 update_growth_dir_from_R(); 00755 update_centroid(); 00756 update_end_pt(); 00757 update_apical(); 00758 update_laterals(); 00759 update_ancestry_log_prob(); 00760 } 00761 catch (Arg_error e) 00762 { 00763 if (entry < 2) 00764 { 00765 set_orientation(old_theta, old_psi); 00766 } 00767 else 00768 { 00769 // TODO the length has been coming up wrong because of precision. 00770 // Probably could throw something like Result_error exception 00771 // here. 00772 entry = 0; 00773 } 00774 throw e; 00775 } 00776 } 00777 00778 00787 void Structure::set_base_orientation(float base_theta, float base_psi) 00788 throw (Arg_error) 00789 { 00790 static int entry = 0; 00791 00792 entry++; 00793 00794 float old_base_theta = this->base_theta; 00795 float old_base_psi = this->base_psi; 00796 00797 try 00798 { 00799 this->base_theta = base_theta; 00800 check_base_theta(); 00801 00802 this->base_psi = base_psi; 00803 check_base_psi(); 00804 00805 update_R(); 00806 update_growth_dir_from_R(); 00807 update_centroid(); 00808 update_end_pt(); 00809 update_apical(); 00810 update_laterals(); 00811 update_ancestry_log_prob(); 00812 } 00813 catch (Arg_error e) 00814 { 00815 if (entry < 2) 00816 { 00817 set_base_orientation(old_base_theta, old_base_psi); 00818 } 00819 else 00820 { 00821 // TODO the length has been coming up wrong because of precision. 00822 // Probably could throw something like Result_error exception 00823 // here. 00824 entry = 0; 00825 } 00826 throw e; 00827 } 00828 } 00829 00830 00838 void Structure::set_opacity(float opacity) throw (Arg_error) 00839 { 00840 static int entry = 0; 00841 00842 entry++; 00843 00844 float old_opacity = this->opacity; 00845 00846 try 00847 { 00848 this->opacity = opacity; 00849 check_opacity(); 00850 00851 update_ancestry_log_prob(); 00852 } 00853 catch (Arg_error e) 00854 { 00855 if (entry < 2) 00856 { 00857 set_opacity(old_opacity); 00858 } 00859 else 00860 { 00861 // TODO the length has been coming up wrong because of precision. 00862 // Probably could throw something like Result_error exception 00863 // here. 00864 entry = 0; 00865 } 00866 throw e; 00867 } 00868 } 00869 00870 00887 bool Structure::recursively_draw_in_matblock_f 00888 ( 00889 jwsc::Matblock_f* M_blk, 00890 float x, 00891 float y, 00892 float z, 00893 float x_scale, 00894 float y_scale, 00895 float z_scale, 00896 bool fill 00897 ) 00898 const 00899 { 00900 bool intersect = false; 00901 00902 if (apical) 00903 { 00904 if (apical->recursively_draw_in_matblock_f(M_blk, x, y, z, x_scale, 00905 y_scale, z_scale, fill)) 00906 { 00907 intersect = true; 00908 } 00909 } 00910 for (list<Lateral_structure*>::const_iterator it = laterals.begin(); 00911 it != laterals.end(); it++) 00912 { 00913 if ((*it)->recursively_draw_in_matblock_f(M_blk, x, y, z, x_scale, 00914 y_scale, z_scale, fill)) 00915 { 00916 intersect = true; 00917 } 00918 } 00919 00920 if (draw_in_matblock_f(M_blk, x, y, z, x_scale, y_scale, z_scale, fill)) 00921 { 00922 intersect = true; 00923 } 00924 00925 return intersect; 00926 } 00927 00928 00933 #if defined ALTERNARIA_HAVE_OPENGL_FRAMEWORK || defined ALTERNARIA_HAVE_OPENGL 00934 void Structure::recursively_draw_in_opengl(GLUquadric* quad, float scale) 00935 const 00936 { 00937 draw_in_opengl(quad, scale); 00938 00939 if (apical) 00940 { 00941 apical->recursively_draw_in_opengl(quad, scale); 00942 } 00943 for (list<Lateral_structure*>::const_iterator it = laterals.begin(); 00944 it != laterals.end(); it++) 00945 { 00946 (*it)->recursively_draw_in_opengl(quad, scale); 00947 } 00948 } 00949 #endif 00950 00951 00956 Structure* Structure::get_terminal_apical() 00957 { 00958 if (apical) 00959 { 00960 return apical->get_terminal_apical(); 00961 } 00962 else 00963 { 00964 return this; 00965 } 00966 } 00967 00968 00975 Lateral_structure* Structure::get_random_lateral() 00976 throw (Result_error) 00977 { 00978 if (laterals.empty()) 00979 { 00980 throw Result_error("Structure contains no laterals"); 00981 } 00982 00983 int u = static_cast<int>( 00984 floor(sample_uniform_pdf_d(0, 0.9999*laterals.size()))); 00985 00986 list<Lateral_structure*>::const_iterator it = laterals.begin(); 00987 00988 for (int i = 0; i < u; i++) 00989 { 00990 it++; 00991 } 00992 00993 return *it; 00994 } 00995 00996 01022 void Structure::print(ostream& out) const 01023 { 01024 out << " Structure: " << get_type_str() << '\n' 01025 << " ID: " << id << '\n' 01026 << " Level: " << level << '\n' 01027 << " Centroid: " << centroid->elts[0] << ' ' 01028 << centroid->elts[1] << ' ' 01029 << centroid->elts[2] << '\n' 01030 << " Length: " << length << '\n' 01031 << " Width: " << width << '\n' 01032 << " Base Theta: " << base_theta << '\n' 01033 << " Base Psi: " << base_psi << '\n' 01034 << " Theta: " << theta << '\n' 01035 << " Psi: " << psi << '\n' 01036 << " Opacity: " << opacity << '\n'; 01037 01038 out << " Parent: " ; 01039 if (parent) 01040 { 01041 out << parent->id; 01042 } 01043 out << '\n'; 01044 01045 out << " Apical: " ; 01046 if (apical) 01047 { 01048 out << apical->id; 01049 } 01050 out << '\n'; 01051 01052 out << " Laterals: "; 01053 for (list<Lateral_structure*>::const_iterator it = laterals.begin(); 01054 it != laterals.end(); it++) 01055 { 01056 out << (*it)->id << ' '; 01057 } 01058 out << '\n'; 01059 01060 out << " Log Prob: " << std::setprecision(10) << log_prob << '\n'; 01061 } 01062 01063 01065 void Structure::recursively_print(ostream& out) const 01066 { 01067 print(out); 01068 01069 if (apical) 01070 { 01071 apical->recursively_print(out); 01072 } 01073 for (list<Lateral_structure*>::const_iterator it = laterals.begin(); 01074 it != laterals.end(); it++) 01075 { 01076 (*it)->recursively_print(out); 01077 } 01078 } 01079 01080 01082 void Structure::recursively_check_structure() const 01083 { 01084 check_width(); 01085 check_length(); 01086 check_theta(); 01087 check_psi(); 01088 check_base_theta(); 01089 check_base_psi(); 01090 check_centroid(); 01091 check_opacity(); 01092 01093 if (apical) 01094 { 01095 assert(fabs(end_pt->elts[0] - apical->begin_pt->elts[0]) < 1.0e-6); 01096 assert(fabs(end_pt->elts[1] - apical->begin_pt->elts[1]) < 1.0e-6); 01097 assert(fabs(end_pt->elts[2] - apical->begin_pt->elts[2]) < 1.0e-6); 01098 apical->recursively_check_structure(); 01099 } 01100 for (list<Lateral_structure*>::const_iterator it = laterals.begin(); 01101 it != laterals.end(); it++) 01102 { 01103 (*it)->recursively_check_structure(); 01104 } 01105 } 01106 01107 01113 bool Structure::has_child_id(uint32_t id) const 01114 { 01115 if (apical && apical->id == id) 01116 { 01117 return true; 01118 } 01119 01120 for (list<Lateral_structure*>::const_iterator it = laterals.begin(); 01121 it != laterals.end(); it++) 01122 { 01123 if ((*it)->id == id) 01124 { 01125 return true; 01126 } 01127 } 01128 01129 return false; 01130 } 01131 01132 01140 void Structure::update_angles() throw (Arg_error) 01141 { 01142 Matrix_f* M = 0; 01143 Vector_f* v = 0; 01144 01145 if (parent) 01146 { 01147 transpose_matrix_f(&M, parent->R); 01148 multiply_matrix_and_vector_f(&v, M, growth_dir); 01149 } 01150 else 01151 { 01152 copy_vector_f(&v, growth_dir); 01153 } 01154 01155 if (base_theta != 0 || base_psi != 0) 01156 { 01157 create_euler_rotation_matrix_f(&M, 0, base_theta, base_psi); 01158 transpose_matrix_f(&M, M); 01159 multiply_matrix_and_vector_f(&v, M, v); 01160 } 01161 01162 double x = v->elts[0]; 01163 double y = v->elts[1]; 01164 double z = v->elts[2]; 01165 01166 bool zero_theta = false; 01167 01168 // Calculate the euler angle psi: rotation about z-axis to put the apical 01169 // growth_dir on the z,(y+) plane. 01170 // 01171 // Check some special cases. 01172 if (fabs(x) < 1.0e-6 && y > -1.0e-6) 01173 { 01174 psi = 0; 01175 if (fabs(y) < 1.0e-6) 01176 { 01177 zero_theta = true; 01178 } 01179 } 01180 else if (fabs(x) < 1.0e-6) 01181 { 01182 psi = JWSC_PI; 01183 } 01184 else 01185 { 01186 double s = std::sqrt(x*x + y*y); 01187 double d = y / s; 01188 01189 if (d > 1) 01190 d = 1; 01191 else if (d < -1) 01192 d = -1; 01193 01194 psi = (x > 0) ? std::acos(d) : -std::acos(d); 01195 01196 #if defined ALTERNARIA_HAVE_ISINF && defined ALTERNARIA_HAVE_ISNAN 01197 assert(!std::isinf(psi) && !std::isnan(psi)); 01198 #endif 01199 } 01200 01201 float min = density->get_psi().get_min(); 01202 float max = density->get_psi().get_max(); 01203 01204 if (psi > max && (psi - JWSC_2_PI) >= min) 01205 { 01206 psi -= JWSC_2_PI; 01207 } 01208 else if (psi < min && (psi + JWSC_2_PI) <= max) 01209 { 01210 psi += JWSC_2_PI; 01211 } 01212 01213 // Undo the psi rotation to put v on the z,(y+) plane. 01214 if (zero_theta) 01215 { 01216 theta = 0; 01217 } 01218 else 01219 { 01220 create_euler_rotation_matrix_f(&M, 0, 0, psi); 01221 transpose_matrix_f(&M, M); 01222 multiply_matrix_and_vector_f(&v, M, v); 01223 01224 y = v->elts[1]; 01225 z = v->elts[2]; 01226 01227 // Calculate the euler angle theta: rotation about the x-axis to put 01228 // apical growth_dir on the z-axis. 01229 assert(y > 0); 01230 01231 if (z > 1) 01232 z = 1; 01233 01234 theta = std::acos(z); 01235 01236 #if defined ALTERNARIA_HAVE_ISINF && defined ALTERNARIA_HAVE_ISNAN 01237 assert(!std::isinf(theta) && !std::isnan(theta)); 01238 #endif 01239 01240 min = density->get_theta().get_min(); 01241 max = density->get_theta().get_max(); 01242 01243 if (theta > max && (theta - JWSC_2_PI) >= min) 01244 { 01245 theta -= JWSC_2_PI; 01246 } 01247 else if (theta < min && (theta + JWSC_2_PI) <= max) 01248 { 01249 theta += JWSC_2_PI; 01250 } 01251 } 01252 01253 free_matrix_f(M); 01254 free_vector_f(v); 01255 01256 check_theta(); 01257 check_psi(); 01258 } 01259 01260 01262 void Structure::update_R() 01263 { 01264 create_euler_rotation_matrix_f(&R, 0, theta, psi); 01265 01266 if (base_theta != 0 || base_psi != 0) 01267 { 01268 Matrix_f* base_R = 0; 01269 create_euler_rotation_matrix_f(&base_R, 0, base_theta, base_psi); 01270 multiply_matrices_f(&R, base_R, R); 01271 free_matrix_f(base_R); 01272 } 01273 01274 if (parent) 01275 { 01276 multiply_matrices_f(&R, parent->R, R); 01277 } 01278 } 01279 01280 01282 void Structure::update_growth_dir_from_R() 01283 { 01284 create_zero_vector_f(&growth_dir, 3); 01285 growth_dir->elts[2] = 1; 01286 01287 multiply_matrix_and_vector_f(&growth_dir, R, growth_dir); 01288 } 01289 01290 01292 void Structure::update_growth_dir_and_length_from_pts() throw (Arg_error) 01293 { 01294 subtract_vectors_f(&growth_dir, end_pt, begin_pt); 01295 calc_vector_mag_f(&length, growth_dir); 01296 normalize_vector_mag_f(&growth_dir, growth_dir); 01297 01298 check_length(); 01299 } 01300 01301 01309 void Structure::update_centroid() throw (Arg_error) 01310 { 01311 multiply_vector_by_scalar_f(¢roid, growth_dir, 0.5f*length); 01312 add_vectors_f(¢roid, centroid, begin_pt); 01313 01314 check_centroid(); 01315 } 01316 01317 01321 void Structure::update_begin_pt() 01322 { 01323 multiply_vector_by_scalar_f(&begin_pt, growth_dir, -0.5*length); 01324 add_vectors_f(&begin_pt, begin_pt, centroid); 01325 } 01326 01327 01331 void Structure::update_end_pt() 01332 { 01333 multiply_vector_by_scalar_f(&end_pt, growth_dir, 0.5*length); 01334 add_vectors_f(&end_pt, end_pt, centroid); 01335 } 01336 01337 01343 void Structure::update_apical() throw (Arg_error) 01344 { 01345 if (!apical) 01346 return; 01347 01348 apical->update_from_parent_end_pt(); 01349 } 01350 01351 01357 void Structure::update_laterals() throw (Arg_error) 01358 { 01359 for (list<Lateral_structure*>::iterator it = laterals.begin(); 01360 it != laterals.end(); it++) 01361 { 01362 (*it)->update_from_parent_end_pt(); 01363 } 01364 } 01365 01366 01368 void Structure::update_log_prob() 01369 { 01370 float mu, sigma; 01371 float min, max; 01372 double delta; 01373 double p_1, p_2; 01374 01375 log_prob = 0; 01376 log_prob_descend = 0; 01377 01378 if (apical) 01379 { 01380 log_prob_descend += apical->log_prob + apical->log_prob_descend; 01381 } 01382 01383 for (list<Lateral_structure*>::iterator it = laterals.begin(); 01384 it != laterals.end(); it++) 01385 { 01386 log_prob_descend += (*it)->log_prob + (*it)->log_prob_descend; 01387 } 01388 01389 /* Length */ 01390 mu = density->get_length().get_mu(); 01391 sigma = density->get_length().get_sigma(); 01392 min = density->get_length().get_min(); 01393 max = density->get_length().get_max(); 01394 delta = (max - min) / 1000; 01395 p_1 = integrate_gaussian_pdf_d(mu, sigma, length, length+delta); 01396 p_2 = integrate_gaussian_pdf_d(mu, sigma, min, max); 01397 log_prob += log((p_1 < JWSC_MIN_LOG_ARG) ? JWSC_MIN_LOG_ARG : p_1); 01398 log_prob -= log((p_2 < JWSC_MIN_LOG_ARG) ? JWSC_MIN_LOG_ARG : p_2); 01399 01400 /* Width */ 01401 mu = density->get_width().get_mu(); 01402 sigma = density->get_width().get_sigma(); 01403 min = density->get_width().get_min(); 01404 max = density->get_width().get_max(); 01405 delta = (max - min) / 1000; 01406 p_1 = integrate_gaussian_pdf_d(mu, sigma, width, width+delta); 01407 p_2 = integrate_gaussian_pdf_d(mu, sigma, min, max); 01408 log_prob += log((p_1 < JWSC_MIN_LOG_ARG) ? JWSC_MIN_LOG_ARG : p_1); 01409 log_prob -= log((p_2 < JWSC_MIN_LOG_ARG) ? JWSC_MIN_LOG_ARG : p_2); 01410 01411 /* Theta */ 01412 mu = density->get_theta().get_mu(); 01413 sigma = density->get_theta().get_sigma(); 01414 min = density->get_theta().get_min(); 01415 max = density->get_theta().get_max(); 01416 delta = (max - min) / 1000; 01417 p_1 = integrate_gaussian_pdf_d(mu, sigma, theta, theta+delta); 01418 p_2 = integrate_gaussian_pdf_d(mu, sigma, min, max); 01419 log_prob += log((p_1 < JWSC_MIN_LOG_ARG) ? JWSC_MIN_LOG_ARG : p_1); 01420 log_prob -= log((p_2 < JWSC_MIN_LOG_ARG) ? JWSC_MIN_LOG_ARG : p_2); 01421 01422 /* Psi */ 01423 min = density->get_psi().get_min(); 01424 max = density->get_psi().get_max(); 01425 log_prob -= log(max - min); 01426 01427 /* Opacity */ 01428 mu = density->get_opacity().get_mu(); 01429 sigma = density->get_opacity().get_sigma(); 01430 min = density->get_opacity().get_min(); 01431 max = density->get_opacity().get_max(); 01432 delta = (max - min) / 1000; 01433 p_1 = integrate_gaussian_pdf_d(mu, sigma, opacity, opacity+delta); 01434 p_2 = integrate_gaussian_pdf_d(mu, sigma, min, max); 01435 log_prob += log((p_1 < JWSC_MIN_LOG_ARG) ? JWSC_MIN_LOG_ARG : p_1); 01436 log_prob -= log((p_2 < JWSC_MIN_LOG_ARG) ? JWSC_MIN_LOG_ARG : p_2); 01437 01438 #if defined ALTERNARIA_HAVE_ISINF && defined ALTERNARIA_HAVE_ISNAN 01439 assert(!std::isinf(log_prob) && !std::isnan(log_prob)); 01440 assert(!std::isinf(log_prob_descend) && !std::isnan(log_prob_descend)); 01441 #endif 01442 } 01443 01444 01449 void Structure::update_ancestry_log_prob() 01450 { 01451 update_log_prob(); 01452 01453 if (parent) 01454 { 01455 parent->update_ancestry_log_prob(); 01456 } 01457 } 01458 01459 01467 void Structure::recursively_update_levels(int level_delta) throw (Result_error) 01468 { 01469 if (level_delta == 0) 01470 { 01471 return; 01472 } 01473 else if (level_delta < 0 && level < static_cast<size_t>(abs(level))) 01474 { 01475 throw Result_error("Structure level < 0"); 01476 } 01477 else 01478 { 01479 if (apical) 01480 { 01481 apical->recursively_update_levels(level_delta); 01482 } 01483 for (list<Lateral_structure*>::iterator it = laterals.begin(); 01484 it != laterals.end(); it++) 01485 { 01486 (*it)->recursively_update_levels(level_delta); 01487 } 01488 level += level_delta; 01489 } 01490 } 01491 01492 01497 void Structure::check_length() const throw (Arg_error) 01498 { 01499 if (density->get_length().get_min() > length || 01500 density->get_length().get_max() < length) 01501 { 01502 ostringstream ost; 01503 ost << "Length " << length << " outside density range [" 01504 << density->get_length().get_min() << ',' 01505 << density->get_length().get_max() << ']'; 01506 throw Arg_error(ost.str()); 01507 } 01508 } 01509 01510 01515 void Structure::check_width() const throw (Arg_error) 01516 { 01517 if (density->get_width().get_min() > width || 01518 density->get_width().get_max() < width) 01519 { 01520 ostringstream ost; 01521 ost << "Width " << width << " outside density range [" 01522 << density->get_width().get_min() << ',' 01523 << density->get_width().get_max() << ']'; 01524 throw Arg_error(ost.str()); 01525 } 01526 } 01527 01528 01533 void Structure::check_theta() const throw (Arg_error) 01534 { 01535 float min = density->get_theta().get_min(); 01536 float max = density->get_theta().get_max(); 01537 01538 if (min > theta || max < theta) 01539 { 01540 ostringstream ost; 01541 ost << "Theta " << theta << " outside density range [" 01542 << min << ',' << max << ']'; 01543 throw Arg_error(ost.str()); 01544 } 01545 } 01546 01547 01552 void Structure::check_base_theta() const throw (Arg_error) 01553 { 01554 float min = 0; 01555 float max = JWSC_PI; 01556 01557 if (min > base_theta || max < base_theta) 01558 { 01559 ostringstream ost; 01560 ost << "Base theta " << base_theta << " outside density range [" 01561 << min << ',' << max << ']'; 01562 throw Arg_error(ost.str()); 01563 } 01564 } 01565 01566 01571 void Structure::check_psi() const throw (Arg_error) 01572 { 01573 float min = density->get_psi().get_min(); 01574 float max = density->get_psi().get_max(); 01575 01576 if (min > psi || max < psi) 01577 { 01578 ostringstream ost; 01579 ost << "Psi " << psi << " outside density range [" 01580 << min << ',' << max << ']'; 01581 throw Arg_error(ost.str()); 01582 } 01583 } 01584 01585 01590 void Structure::check_base_psi() const throw (Arg_error) 01591 { 01592 float min = -JWSC_PI; 01593 float max = JWSC_PI; 01594 01595 if (min > base_psi || max < base_psi) 01596 { 01597 ostringstream ost; 01598 ost << "Base psi " << base_psi << " outside density range [" 01599 << min << ',' << max << ']'; 01600 throw Arg_error(ost.str()); 01601 } 01602 } 01603 01604 01609 void Structure::check_opacity() const throw (Arg_error) 01610 { 01611 if (density->get_opacity().get_min() > opacity || 01612 density->get_opacity().get_max() < opacity) 01613 { 01614 ostringstream ost; 01615 ost << "Opacity " << opacity << " outside density range [" 01616 << density->get_opacity().get_min() << ',' 01617 << density->get_opacity().get_max() << ']'; 01618 throw Arg_error(ost.str()); 01619 } 01620 } 01621 01622 01624 uint32_t Structure::generate_id() 01625 { 01626 static uint32_t next_id = 1; 01627 return next_id++; 01628 } 01629 01630 01631 /* -------------------------------------------------------------------------- */ 01632 01633 01634 01635 01636 01637 01638 01639 /* ------------------------- Printed_structure ---------------------------- */ 01640 01648 void Printed_structure::read_id(std::istream& in) throw (IO_error, Arg_error) 01649 { 01650 const char* member_value; 01651 01652 if (!(member_value = Structure::get_member_value("ID", in))) 01653 { 01654 throw Arg_error("Structure missing ID"); 01655 } 01656 istringstream ist(member_value); 01657 ist >> id; 01658 if (ist.fail()) 01659 { 01660 throw Arg_error("Structure has invalid ID"); 01661 } 01662 } 01663 01664 01672 void Printed_structure::read_level(std::istream& in) throw (IO_error, Arg_error) 01673 { 01674 const char* member_value; 01675 01676 if (!(member_value = Structure::get_member_value("Level", in))) 01677 { 01678 throw Arg_error("Structure missing level"); 01679 } 01680 istringstream ist(member_value); 01681 ist >> level; 01682 if (ist.fail()) 01683 { 01684 throw Arg_error("Structure has invalid level"); 01685 } 01686 } 01687 01688 01696 void Printed_structure::read_centroid(std::istream& in) 01697 throw (IO_error, Arg_error) 01698 { 01699 const char* member_value; 01700 01701 // Centroid X 01702 if (!(member_value = Structure::get_member_value("Centroid", in))) 01703 { 01704 throw Arg_error("Missing centroid x"); 01705 } 01706 istringstream ist(member_value); 01707 ist >> centroid_x; 01708 if (ist.fail()) 01709 { 01710 throw Arg_error("Invalid centroid x"); 01711 } 01712 ist.clear(std::ios_base::goodbit); 01713 01714 // Centroid Y 01715 if (!(member_value = Structure::get_next_member_value(member_value))) 01716 { 01717 throw Arg_error("Missing centroid y"); 01718 } 01719 ist.str(member_value); 01720 ist >> centroid_y; 01721 if (ist.fail()) 01722 { 01723 throw Arg_error("Invalid centroid y"); 01724 } 01725 ist.clear(std::ios_base::goodbit); 01726 01727 // Centroid Z 01728 if (!(member_value = Structure::get_next_member_value(member_value))) 01729 { 01730 throw Arg_error("Missing centroid z"); 01731 } 01732 ist.str(member_value); 01733 ist >> centroid_z; 01734 if (ist.fail()) 01735 { 01736 throw Arg_error("Invalid centroid z"); 01737 } 01738 ist.clear(std::ios_base::goodbit); 01739 } 01740 01741 01749 void Printed_structure::read_length(std::istream& in) 01750 throw (IO_error, Arg_error) 01751 { 01752 const char* member_value; 01753 01754 if (!(member_value = Structure::get_member_value("Length", in))) 01755 { 01756 throw Arg_error("Missing length"); 01757 } 01758 istringstream ist(member_value); 01759 ist >> length; 01760 if (ist.fail()) 01761 { 01762 throw Arg_error("Invalid length"); 01763 } 01764 } 01765 01766 01774 void Printed_structure::read_width(std::istream& in) 01775 throw (IO_error, Arg_error) 01776 { 01777 const char* member_value; 01778 01779 if (!(member_value = Structure::get_member_value("Width", in))) 01780 { 01781 throw Arg_error("Missing width"); 01782 } 01783 istringstream ist(member_value); 01784 ist >> width; 01785 if (ist.fail()) 01786 { 01787 throw Arg_error("Invalid width"); 01788 } 01789 } 01790 01791 01799 void Printed_structure::read_theta(std::istream& in) 01800 throw (IO_error, Arg_error) 01801 { 01802 const char* member_value; 01803 01804 if (!(member_value = Structure::get_member_value("Theta", in))) 01805 { 01806 throw Arg_error("Missing theta"); 01807 } 01808 istringstream ist(member_value); 01809 ist >> theta; 01810 if (ist.fail()) 01811 { 01812 throw Arg_error("Invalid theta"); 01813 } 01814 } 01815 01816 01824 void Printed_structure::read_base_theta(std::istream& in) 01825 throw (IO_error, Arg_error) 01826 { 01827 const char* member_value; 01828 01829 if (!(member_value = Structure::get_member_value("Base Theta", in))) 01830 { 01831 throw Arg_error("Missing base theta"); 01832 } 01833 istringstream ist(member_value); 01834 ist >> base_theta; 01835 if (ist.fail()) 01836 { 01837 throw Arg_error("Invalid base theta"); 01838 } 01839 } 01840 01841 01849 void Printed_structure::read_psi(std::istream& in) 01850 throw (IO_error, Arg_error) 01851 { 01852 const char* member_value; 01853 01854 if (!(member_value = Structure::get_member_value("Psi", in))) 01855 { 01856 throw Arg_error("Missing psi"); 01857 } 01858 istringstream ist(member_value); 01859 ist >> psi; 01860 if (ist.fail()) 01861 { 01862 throw Arg_error("Invalid psi"); 01863 } 01864 } 01865 01866 01874 void Printed_structure::read_base_psi(std::istream& in) 01875 throw (IO_error, Arg_error) 01876 { 01877 const char* member_value; 01878 01879 if (!(member_value = Structure::get_member_value("Base Psi", in))) 01880 { 01881 throw Arg_error("Missing base psi"); 01882 } 01883 istringstream ist(member_value); 01884 ist >> base_psi; 01885 if (ist.fail()) 01886 { 01887 throw Arg_error("Invalid base psi"); 01888 } 01889 } 01890 01891 01899 void Printed_structure::read_opacity(std::istream& in) 01900 throw (IO_error, Arg_error) 01901 { 01902 const char* member_value; 01903 01904 if (!(member_value = Structure::get_member_value("Opacity", in))) 01905 { 01906 throw Arg_error("Missing opacity"); 01907 } 01908 istringstream ist(member_value); 01909 ist >> opacity; 01910 if (ist.fail()) 01911 { 01912 throw Arg_error("Invalid opacity"); 01913 } 01914 } 01915 01916 01924 void Printed_structure::read_log_prob(std::istream& in) 01925 throw (IO_error, Arg_error) 01926 { 01927 const char* member_value; 01928 01929 if (!(member_value = Structure::get_member_value("Log Prob", in))) 01930 { 01931 throw Arg_error("Missing log probability"); 01932 } 01933 istringstream ist(member_value); 01934 ist >> log_prob; 01935 if (ist.fail()) 01936 { 01937 throw Arg_error("Invalid log probability"); 01938 } 01939 } 01940 01941 01948 void Printed_structure::read_parent(std::istream& in) 01949 throw (IO_error, Arg_error) 01950 { 01951 const char* member_value; 01952 01953 parent = 0; 01954 if ((member_value = Structure::get_member_value("Parent", in))) 01955 { 01956 istringstream ist(member_value); 01957 ist >> parent; 01958 if (ist.fail()) 01959 { 01960 throw Arg_error("Invalid parent"); 01961 } 01962 } 01963 } 01964 01965 01972 void Printed_structure::read_apical(std::istream& in) 01973 throw (IO_error, Arg_error) 01974 { 01975 const char* member_value; 01976 01977 apical = 0; 01978 if ((member_value = Structure::get_member_value("Apical", in))) 01979 { 01980 istringstream ist(member_value); 01981 ist >> apical; 01982 if (ist.fail()) 01983 { 01984 throw Arg_error("Invalid apical"); 01985 } 01986 } 01987 } 01988 01989 01996 void Printed_structure::read_laterals(std::istream& in) 01997 throw (IO_error, Arg_error) 01998 { 01999 const char* member_value; 02000 02001 laterals.clear(); 02002 if ((member_value = Structure::get_member_value("Laterals", in))) 02003 { 02004 uint32_t lateral; 02005 istringstream ist(member_value); 02006 ist >> lateral; 02007 02008 laterals.push_back(lateral); 02009 while ((member_value = Structure::get_next_member_value(member_value))) 02010 { 02011 ist.str(member_value); 02012 ist >> lateral; 02013 if (ist.fail()) 02014 { 02015 throw Arg_error("Invalid lateral"); 02016 } 02017 ist.clear(std::ios_base::goodbit); 02018 laterals.push_back(lateral); 02019 } 02020 } 02021 } 02022 02023 02032 bool Printed_structure::is_on_istream(std::istream& in, const char* type_str) 02033 throw (IO_error, Arg_error) 02034 { 02035 const char* member_value; 02036 02037 streampos in_posn = in.tellg(); 02038 02039 if (!(member_value = Structure::get_member_value("Structure", in))) 02040 { 02041 throw Arg_error("Missing structure type"); 02042 } 02043 02044 in.seekg(in_posn); 02045 02046 if (strncmp(member_value, type_str, strlen(type_str)) != 0) 02047 { 02048 return false; 02049 } 02050 02051 return true; 02052 } 02053 02054 /* -------------------------------------------------------------------------- */ 02055 02056 02057 02058 02059 02060 02061 02062 /* ------------------------- Apical_structure ----------------------------- */ 02063 02081 Apical_structure::Apical_structure 02082 ( 02083 float centroid_x, 02084 float centroid_y, 02085 float centroid_z, 02086 float length, 02087 float width, 02088 float base_theta, 02089 float base_psi, 02090 float theta, 02091 float psi, 02092 float opacity, 02093 size_t level, 02094 const class Apical_structure_density* density 02095 ) 02096 throw (Arg_error) 02097 : Structure(length, width, base_theta, base_psi, theta, psi, opacity, 02098 level, density) 02099 { 02100 this->density = density; 02101 02102 create_vector_f(¢roid, 3); 02103 centroid->elts[0] = centroid_x; 02104 centroid->elts[1] = centroid_y; 02105 centroid->elts[2] = centroid_z; 02106 02107 check_centroid(); 02108 02109 update_R(); 02110 update_growth_dir_from_R(); 02111 update_begin_pt(); 02112 update_end_pt(); 02113 } 02114 02115 02131 Apical_structure::Apical_structure 02132 ( 02133 Structure* parent, 02134 float length, 02135 float width, 02136 float base_theta, 02137 float base_psi, 02138 float theta, 02139 float psi, 02140 float opacity, 02141 const class Apical_structure_density* density 02142 ) 02143 throw (Arg_error, Apical_error) 02144 : Structure(length, width, base_theta, base_psi, theta, psi, opacity, 02145 parent->level, density) 02146 { 02147 if (parent->apical) 02148 { 02149 throw Apical_error("Structure already contains an apical growth"); 02150 } 02151 02152 this->parent = parent; 02153 this->density = density; 02154 02155 copy_vector_f(&begin_pt, parent->end_pt); 02156 02157 update_R(); 02158 update_growth_dir_from_R(); 02159 update_centroid(); 02160 update_end_pt(); 02161 02162 parent->apical = this; 02163 } 02164 02165 02182 Apical_structure::Apical_structure 02183 ( 02184 Structure* parent, 02185 float centroid_x, 02186 float centroid_y, 02187 float centroid_z, 02188 float length, 02189 float width, 02190 float base_theta, 02191 float base_psi, 02192 float opacity, 02193 const class Apical_structure_density* density 02194 ) 02195 throw (Arg_error, Apical_error) 02196 : Structure(length, width, base_theta, base_psi, parent->theta, 02197 parent->psi, opacity, parent->level, density) 02198 { 02199 if (parent->apical) 02200 { 02201 throw Apical_error("Structure already contains an apical growth"); 02202 } 02203 02204 this->parent = parent; 02205 this->density = density; 02206 02207 create_vector_f(¢roid, 3); 02208 centroid->elts[0] = centroid_x; 02209 centroid->elts[1] = centroid_y; 02210 centroid->elts[2] = centroid_z; 02211 check_centroid(); 02212 02213 copy_vector_f(&begin_pt, parent->end_pt); 02214 02215 subtract_vectors_f(&growth_dir, centroid, begin_pt); 02216 normalize_vector_mag_f(&growth_dir, growth_dir); 02217 02218 update_end_pt(); 02219 update_angles(); 02220 update_R(); 02221 02222 parent->apical = this; 02223 } 02224 02225 02227 Apical_structure::Apical_structure(const Apical_structure& s) : Structure(s) 02228 { 02229 density = s.density; 02230 } 02231 02232 02234 Apical_structure* Apical_structure::recursively_clone() const 02235 { 02236 Apical_structure* s = clone(); 02237 02238 s->apical = 0; 02239 s->laterals.clear(); 02240 02241 if (apical) 02242 { 02243 s->apical = apical->recursively_clone(); 02244 s->apical->parent = s; 02245 } 02246 for (list<Lateral_structure*>::const_iterator it = laterals.begin(); 02247 it != laterals.end(); it++) 02248 { 02249 Lateral_structure* lateral = (*it)->recursively_clone(); 02250 s->laterals.push_back(lateral); 02251 lateral->parent = s; 02252 } 02253 02254 return s; 02255 } 02256 02257 02263 Apical_structure& Apical_structure::operator= (const Apical_structure& s) 02264 { 02265 Structure::operator=(s); 02266 02267 density = s.density; 02268 02269 return *this; 02270 } 02271 02272 02282 void Apical_structure::set_position 02283 ( 02284 float centroid_x, 02285 float centroid_y, 02286 float centroid_z 02287 ) 02288 throw (jwscxx::base::Arg_error) 02289 { 02290 static int entry = 0; 02291 02292 entry++; 02293 02294 Vector_f* old_centroid = 0; 02295 copy_vector_f(&old_centroid, centroid); 02296 02297 Vector_f* T = 0; 02298 copy_vector_f(&T, centroid); 02299 T->elts[0] = centroid_x - T->elts[0]; 02300 T->elts[1] = centroid_y - T->elts[1]; 02301 T->elts[2] = centroid_z - T->elts[2]; 02302 02303 float mag; 02304 calc_vector_mag_f(&mag, T); 02305 if (mag < 1.0e-2) 02306 { 02307 free_vector_f(old_centroid); 02308 free_vector_f(T); 02309 return; 02310 } 02311 02312 try 02313 { 02314 add_vectors_f(&begin_pt, begin_pt, T); 02315 add_vectors_f(&end_pt, end_pt, T); 02316 update_growth_dir_and_length_from_pts(); 02317 update_centroid(); 02318 02319 if (parent) 02320 { 02321 copy_vector_f(&(parent->end_pt), begin_pt); 02322 parent->update_growth_dir_and_length_from_pts(); 02323 parent->update_centroid(); 02324 parent->update_angles(); 02325 parent->update_R(); 02326 parent->update_laterals(); 02327 } 02328 02329 02330 update_angles(); 02331 update_R(); 02332 update_laterals(); 02333 02334 if (apical) 02335 { 02336 copy_vector_f(&(apical->begin_pt), end_pt); 02337 apical->update_growth_dir_and_length_from_pts(); 02338 apical->update_centroid(); 02339 apical->update_angles(); 02340 apical->update_R(); 02341 apical->update_apical(); 02342 apical->update_laterals(); 02343 apical->update_ancestry_log_prob(); 02344 } 02345 else 02346 { 02347 update_ancestry_log_prob(); 02348 } 02349 02350 } 02351 catch (Arg_error e) 02352 { 02353 if (entry < 2) 02354 { 02355 set_position(old_centroid->elts[0], old_centroid->elts[1], 02356 old_centroid->elts[2]); 02357 } 02358 else 02359 { 02360 // TODO the length has been coming up wrong because of precision. 02361 // Probably could throw something like Result_error exception 02362 // here. 02363 entry = 0; 02364 } 02365 free_vector_f(old_centroid); 02366 free_vector_f(T); 02367 throw e; 02368 } 02369 02370 free_vector_f(old_centroid); 02371 free_vector_f(T); 02372 02373 entry = 0; 02374 } 02375 02376 02387 Apical_structure* Apical_structure::split_into_apical 02388 ( 02389 const Apical_structure* rvals_1, 02390 const Apical_structure* rvals_2 02391 ) 02392 throw (Arg_error) 02393 { 02394 Apical_structure* split = clone(); 02395 split->id = generate_id(); 02396 split->base_theta = rvals_2->get_base_theta(); 02397 split->base_psi = rvals_2->get_base_psi(); 02398 02399 if (split->apical) 02400 { 02401 split->apical->parent = split; 02402 } 02403 apical = split; 02404 split->parent = this; 02405 02406 // Back-up some of the structure in case of failure. 02407 float old_theta = theta; 02408 float old_psi = psi; 02409 float old_length = length; 02410 float old_width = width; 02411 float old_opacity = opacity; 02412 02413 Vector_f* old_growth_dir = 0; 02414 copy_vector_f(&old_growth_dir, growth_dir); 02415 02416 list<Lateral_structure*> old_laterals = laterals; 02417 02418 list<float> old_lat_dists; 02419 list<Lateral_structure*>::iterator lat_it; 02420 for (lat_it = laterals.begin(); lat_it != laterals.end(); lat_it++) 02421 { 02422 old_lat_dists.push_back((*lat_it)->lat_dist); 02423 } 02424 02425 // Try the split. 02426 try 02427 { 02428 theta = rvals_1->get_theta(); 02429 psi = rvals_1->get_psi(); 02430 width = rvals_1->get_width(); 02431 length = 0.5f*(length + 02432 (rvals_1->get_length() - density->get_length().get_mu())); 02433 opacity = rvals_1->get_opacity(); 02434 02435 check_length(); 02436 02437 update_R(); 02438 update_growth_dir_from_R(); 02439 update_centroid(); 02440 update_end_pt(); 02441 02442 split->width = rvals_2->get_width(); 02443 split->opacity = rvals_2->get_opacity(); 02444 02445 float t; 02446 calc_vector_dot_prod_f(&t, old_growth_dir, growth_dir); 02447 t *= length / old_length; 02448 02449 laterals.clear(); 02450 split->laterals.clear(); 02451 02452 for (lat_it = old_laterals.begin(); lat_it != old_laterals.end(); 02453 lat_it++) 02454 { 02455 if ((*lat_it)->lat_dist < t) 02456 { 02457 (*lat_it)->lat_dist /= t; 02458 laterals.push_back((*lat_it)); 02459 } 02460 else 02461 { 02462 (*lat_it)->lat_dist = ((*lat_it)->lat_dist - t) / (1 - t); 02463 (*lat_it)->parent = split; 02464 split->laterals.push_back((*lat_it)); 02465 } 02466 02467 (*lat_it)->check_lat_dist(); 02468 } 02469 02470 update_apical(); 02471 update_laterals(); 02472 02473 update_ancestry_log_prob(); 02474 } 02475 catch (Arg_error e) 02476 { 02477 if ((apical = split->apical)) 02478 { 02479 apical->parent = this; 02480 } 02481 02482 split->apical = 0; 02483 split->laterals.clear(); 02484 delete split; 02485 02486 theta = old_theta; 02487 psi = old_psi; 02488 length = old_length; 02489 width = old_width; 02490 opacity = old_opacity; 02491 laterals = old_laterals; 02492 02493 free_vector_f(old_growth_dir); 02494 02495 list<float>::iterator dists_it = old_lat_dists.begin(); 02496 for (lat_it = laterals.begin(); lat_it != laterals.end(); lat_it++) 02497 { 02498 (*lat_it)->lat_dist = *dists_it; 02499 (*lat_it)->parent = this; 02500 dists_it++; 02501 } 02502 02503 update_R(); 02504 update_growth_dir_from_R(); 02505 update_centroid(); 02506 update_end_pt(); 02507 update_apical(); 02508 update_laterals(); 02509 02510 throw e; 02511 } 02512 02513 free_vector_f(old_growth_dir); 02514 02515 return split; 02516 } 02517 02518 02533 Apical_structure* Apical_structure::merge_with_apical 02534 ( 02535 const Apical_structure* rvals 02536 ) 02537 throw (Arg_error) 02538 { 02539 Apical_structure* merged = apical; 02540 02541 if (!merged) 02542 { 02543 throw Arg_error("No apical to merge with"); 02544 } 02545 02546 list<Lateral_structure*>::iterator it; 02547 02548 // Back-up some of the structures in case of failure. 02549 Apical_structure* this_clone = this->clone(); 02550 Apical_structure* merged_clone = merged->clone(); 02551 02552 list<float> this_lat_dists; 02553 for (it = laterals.begin(); it != laterals.end(); it++) 02554 { 02555 this_lat_dists.push_back((*it)->lat_dist); 02556 } 02557 list<float> merged_lat_dists; 02558 for (it = merged->laterals.begin(); it != merged->laterals.end(); it++) 02559 { 02560 merged_lat_dists.push_back((*it)->lat_dist); 02561 } 02562 02563 // Try the merge. 02564 try 02565 { 02566 width = rvals->get_width(); 02567 opacity = rvals->get_opacity(); 02568 02569 copy_vector_f(&end_pt, merged->end_pt); 02570 02571 update_growth_dir_and_length_from_pts(); 02572 update_angles(); 02573 update_R(); 02574 update_centroid(); 02575 02576 if ((apical = merged->apical)) 02577 { 02578 apical->parent = this; 02579 } 02580 update_apical(); 02581 02582 float this_dp; 02583 calc_vector_dot_prod_f(&this_dp, this_clone->growth_dir, growth_dir); 02584 02585 float merged_dp; 02586 calc_vector_dot_prod_f(&merged_dp, merged_clone->growth_dir,growth_dir); 02587 02588 // update lat_dist 02589 for (it = laterals.begin(); it != laterals.end(); it++) 02590 { 02591 (*it)->lat_dist *= this_dp * this_clone->length / length; 02592 02593 (*it)->check_lat_dist(); 02594 } 02595 for (it = merged->laterals.begin(); it != merged->laterals.end(); it++) 02596 { 02597 (*it)->lat_dist = 02598 ((*it)->lat_dist * merged_dp * merged_clone->length 02599 + this_dp * this_clone->length) / length; 02600 02601 (*it)->check_lat_dist(); 02602 02603 (*it)->parent = this; 02604 laterals.push_back(*it); 02605 } 02606 update_laterals(); 02607 02608 update_ancestry_log_prob(); 02609 } 02610 catch (Arg_error e) 02611 { 02612 // Undo the changes to the merged Apical_structure. 02613 *merged = *merged_clone; 02614 if (merged->apical) 02615 { 02616 merged->apical->parent = merged; 02617 } 02618 merged->update_apical(); 02619 02620 list<float>::iterator lat_dist_it = merged_lat_dists.begin(); 02621 02622 for (it = merged->laterals.begin(); it != merged->laterals.end(); it++) 02623 { 02624 (*it)->parent = merged; 02625 (*it)->lat_dist = *lat_dist_it; 02626 lat_dist_it++; 02627 } 02628 merged->update_laterals(); 02629 02630 // Undo effects to this Apical_structure. 02631 *this = *this_clone; 02632 02633 lat_dist_it = this_lat_dists.begin(); 02634 02635 for (it = laterals.begin(); it != laterals.end(); it++) 02636 { 02637 (*it)->parent = this; 02638 (*it)->lat_dist = *lat_dist_it; 02639 lat_dist_it++; 02640 } 02641 update_laterals(); 02642 02643 this_clone->apical = 0; 02644 this_clone->laterals.clear(); 02645 merged_clone->apical = 0; 02646 merged_clone->laterals.clear(); 02647 delete this_clone; 02648 delete merged_clone; 02649 02650 throw e; 02651 } 02652 02653 // Clear the laterals and the apical so the merged apical can be deleted. 02654 merged->apical = 0; 02655 merged->laterals.clear(); 02656 02657 // Clear the laterals and the apical so the backups can be deleted. 02658 this_clone->apical = 0; 02659 this_clone->laterals.clear(); 02660 merged_clone->apical = 0; 02661 merged_clone->laterals.clear(); 02662 delete this_clone; 02663 delete merged_clone; 02664 02665 return merged; 02666 } 02667 02668 02679 Lateral_structure* Apical_structure::split_into_lateral 02680 ( 02681 const Apical_structure* rvals_1, 02682 const Lateral_structure* rvals_2 02683 ) 02684 throw (Arg_error) 02685 { 02686 Lateral_structure* split = rvals_2->clone(); 02687 split->parent = this; 02688 split->level = level; 02689 split->id = generate_id(); 02690 split->apical = apical; 02691 copy_vector_f(&(split->end_pt), end_pt); 02692 02693 if (apical) 02694 { 02695 apical->parent = split; 02696 apical = 0; 02697 } 02698 02699 // Back-up some of the structure in case of failure. 02700 float old_theta = theta; 02701 float old_psi = psi; 02702 float old_length = length; 02703 float old_width = width; 02704 02705 Vector_f* old_growth_dir = 0; 02706 copy_vector_f(&old_growth_dir, growth_dir); 02707 02708 list<Lateral_structure*> old_laterals = laterals; 02709 02710 list<float> old_lat_dists; 02711 list<Lateral_structure*>::iterator lat_it; 02712 for (lat_it = laterals.begin(); lat_it != laterals.end(); lat_it++) 02713 { 02714 old_lat_dists.push_back((*lat_it)->lat_dist); 02715 } 02716 02717 // Try the split. 02718 try 02719 { 02720 theta = rvals_1->get_theta(); 02721 psi = rvals_1->get_psi(); 02722 width = rvals_1->get_width(); 02723 length = 0.5f*(length + 02724 (rvals_1->get_length() - density->get_length().get_mu())); 02725 02726 check_length(); 02727 02728 update_R(); 02729 update_growth_dir_from_R(); 02730 update_centroid(); 02731 update_end_pt(); 02732 02733 float dp; 02734 calc_vector_dot_prod_f(&dp, old_growth_dir, growth_dir); 02735 float t1 = dp*length / old_length; 02736 float t2 = dp*split->lat_dist*length / old_length; 02737 02738 laterals.clear(); 02739 split->laterals.clear(); 02740 02741 for (lat_it = old_laterals.begin(); lat_it != old_laterals.end(); 02742 lat_it++) 02743 { 02744 if ((*lat_it)->lat_dist < t1) 02745 { 02746 (*lat_it)->lat_dist /= t1; 02747 laterals.push_back((*lat_it)); 02748 } 02749 else 02750 { 02751 (*lat_it)->lat_dist = ((*lat_it)->lat_dist - t2) / (1 - t2); 02752 (*lat_it)->parent = split; 02753 split->laterals.push_back((*lat_it)); 02754 } 02755 02756 (*lat_it)->check_lat_dist(); 02757 } 02758 02759 laterals.push_back(split); 02760 update_laterals(); 02761 02762 split->recursively_update_levels(1); 02763 02764 update_ancestry_log_prob(); 02765 } 02766 catch (Arg_error e) 02767 { 02768 if ((apical = split->apical)) 02769 { 02770 apical->parent = this; 02771 } 02772 02773 split->apical = 0; 02774 split->laterals.clear(); 02775 delete split; 02776 02777 theta = old_theta; 02778 psi = old_psi; 02779 length = old_length; 02780 width = old_width; 02781 laterals = old_laterals; 02782 02783 free_vector_f(old_growth_dir); 02784 02785 list<float>::iterator dists_it = old_lat_dists.begin(); 02786 for (lat_it = laterals.begin(); lat_it != laterals.end(); lat_it++) 02787 { 02788 (*lat_it)->lat_dist = *dists_it; 02789 (*lat_it)->parent = this; 02790 dists_it++; 02791 } 02792 02793 update_R(); 02794 update_growth_dir_from_R(); 02795 update_centroid(); 02796 update_end_pt(); 02797 update_apical(); 02798 update_laterals(); 02799 02800 throw e; 02801 } 02802 02803 free_vector_f(old_growth_dir); 02804 02805 return split; 02806 } 02807 02808 02823 Lateral_structure* Apical_structure::merge_with_lateral 02824 ( 02825 Lateral_structure* lateral, 02826 const Apical_structure* rvals 02827 ) 02828 throw (Arg_error) 02829 { 02830 list<Lateral_structure*>::iterator it; 02831 bool found = 0; 02832 02833 for (it = laterals.begin(); !found && it != laterals.end(); it++) 02834 { 02835 if (*it == lateral) 02836 found = 1; 02837 } 02838 02839 if (!found) 02840 { 02841 throw Arg_error("Lateral to merge with not found in apical"); 02842 } 02843 02844 Lateral_structure* merged = lateral; 02845 02846 // Back-up some of the structures in case of failure. 02847 Apical_structure* this_clone = this->clone(); 02848 Lateral_structure* merged_clone = merged->clone(); 02849 02850 list<float> this_lat_dists; 02851 for (it = laterals.begin(); it != laterals.end(); it++) 02852 { 02853 this_lat_dists.push_back((*it)->lat_dist); 02854 } 02855 list<float> merged_lat_dists; 02856 for (it = merged->laterals.begin(); it != merged->laterals.end(); it++) 02857 { 02858 merged_lat_dists.push_back((*it)->lat_dist); 02859 } 02860 02861 // Remove merged from this laterals. 02862 for (it = laterals.begin(); it != laterals.end(); it++) 02863 { 02864 if ((*it) == merged) 02865 { 02866 laterals.erase(it); 02867 break; 02868 } 02869 } 02870 02871 // Try the merge. 02872 try 02873 { 02874 width = rvals->get_width(); 02875 02876 copy_vector_f(&end_pt, merged->end_pt); 02877 02878 update_growth_dir_and_length_from_pts(); 02879 update_angles(); 02880 update_R(); 02881 update_centroid(); 02882 02883 if ((apical = merged->apical)) 02884 { 02885 apical->parent = this; 02886 } 02887 update_apical(); 02888 02889 float this_dp; 02890 calc_vector_dot_prod_f(&this_dp, this_clone->growth_dir, growth_dir); 02891 02892 float merged_dp; 02893 calc_vector_dot_prod_f(&merged_dp, merged_clone->growth_dir,growth_dir); 02894 02895 // update lat_dist 02896 for (it = laterals.begin(); it != laterals.end(); it++) 02897 { 02898 (*it)->lat_dist *= this_dp * this_clone->length / length; 02899 02900 (*it)->check_lat_dist(); 02901 } 02902 for (it = merged->laterals.begin(); it != merged->laterals.end(); it++) 02903 { 02904 (*it)->lat_dist = 02905 ((*it)->lat_dist * merged_dp * merged_clone->length 02906 + this_dp * merged_clone->lat_dist * this_clone->length) 02907 / length; 02908 02909 (*it)->check_lat_dist(); 02910 02911 (*it)->parent = this; 02912 laterals.push_back(*it); 02913 } 02914 update_laterals(); 02915 02916 merged->recursively_update_levels(-1); 02917 02918 update_ancestry_log_prob(); 02919 } 02920 catch (Arg_error e) 02921 { 02922 // Undo the changes to the merged Lateral_structure. 02923 *merged = *merged_clone; 02924 if (merged->apical) 02925 { 02926 merged->apical->parent = merged; 02927 } 02928 merged->update_apical(); 02929 02930 list<float>::iterator lat_dist_it = merged_lat_dists.begin(); 02931 02932 for (it = merged->laterals.begin(); it != merged->laterals.end(); it++) 02933 { 02934 (*it)->parent = merged; 02935 (*it)->lat_dist = *lat_dist_it; 02936 lat_dist_it++; 02937 } 02938 merged->update_laterals(); 02939 02940 // Undo effects to this Apical_structure. 02941 *this = *this_clone; 02942 02943 lat_dist_it = this_lat_dists.begin(); 02944 02945 for (it = laterals.begin(); it != laterals.end(); it++) 02946 { 02947 (*it)->parent = this; 02948 (*it)->lat_dist = *lat_dist_it; 02949 lat_dist_it++; 02950 } 02951 update_laterals(); 02952 02953 this_clone->apical = 0; 02954 this_clone->laterals.clear(); 02955 merged_clone->apical = 0; 02956 merged_clone->laterals.clear(); 02957 delete this_clone; 02958 delete merged_clone; 02959 02960 throw e; 02961 } 02962 02963 // Clear the laterals and the apical so the merged apical can be deleted. 02964 merged->apical = 0; 02965 merged->laterals.clear(); 02966 02967 // Clear the laterals and the apical so the backups can be deleted. 02968 this_clone->apical = 0; 02969 this_clone->laterals.clear(); 02970 merged_clone->apical = 0; 02971 merged_clone->laterals.clear(); 02972 delete this_clone; 02973 delete merged_clone; 02974 02975 return merged; 02976 } 02977 02978 02979 02985 void Apical_structure::replace(Apical_structure* s) throw (Arg_error) 02986 { 02987 static int entry = 0; 02988 02989 entry++; 02990 02991 try 02992 { 02993 s->apical = apical; 02994 if (apical) 02995 { 02996 apical->parent = s; 02997 apical = 0; 02998 } 02999 03000 s->laterals.clear(); 03001 for (list<Lateral_structure*>::iterator it = laterals.begin(); 03002 it != laterals.end(); it++) 03003 { 03004 s->laterals.push_back(*it); 03005 (*it)->parent = s; 03006 } 03007 laterals.clear(); 03008 03009 s->parent = parent; 03010 if (parent) 03011 { 03012 parent->apical = s; 03013 parent = 0; 03014 } 03015 03016 s->update_apical(); 03017 s->update_laterals(); 03018 s->update_ancestry_log_prob(); 03019 } 03020 catch (Arg_error e) 03021 { 03022 if (entry < 2) 03023 { 03024 s->replace(this); 03025 } 03026 else 03027 { 03028 // TODO 03029 // Probably could throw something like Result_error exception 03030 // here. 03031 entry = 0; 03032 } 03033 throw e; 03034 } 03035 03036 entry = 0; 03037 } 03038 03039 03040 03041 /* 03042 * @throw jwscxx::base::Arg_error Apical_structure values are not in the 03043 * density parameter range. 03044 */ 03045 void Apical_structure::update_from_parent_end_pt() throw (Arg_error) 03046 { 03047 assert(parent); 03048 03049 copy_vector_f(&begin_pt, parent->end_pt); 03050 03051 update_growth_dir_and_length_from_pts(); 03052 update_angles(); 03053 update_R(); 03054 update_centroid(); 03055 if (apical) 03056 { 03057 apical->update_from_parent_end_pt(); 03058 } 03059 update_laterals(); 03060 03061 update_log_prob(); 03062 } 03063 03064 03066 void Apical_structure::update_log_prob() 03067 { 03068 float min, max; 03069 03070 Structure::update_log_prob(); 03071 03072 /* Centroid_x */ 03073 min = density->get_centroid_x().get_min(); 03074 max = density->get_centroid_x().get_max(); 03075 log_prob -= log(max - min); 03076 03077 /* Centroid_y */ 03078 min = density->get_centroid_y().get_min(); 03079 max = density->get_centroid_y().get_max(); 03080 log_prob -= log(max - min); 03081 03082 /* Centroid_x */ 03083 min = density->get_centroid_z().get_min(); 03084 max = density->get_centroid_z().get_max(); 03085 log_prob -= log(max - min); 03086 03087 #if defined ALTERNARIA_HAVE_ISINF && defined ALTERNARIA_HAVE_ISNAN 03088 assert(!std::isinf(log_prob) && !std::isnan(log_prob)); 03089 #endif 03090 } 03091 03092 03097 void Apical_structure::check_centroid() const throw (Arg_error) 03098 { 03099 if (density->get_centroid_x().get_min() > centroid->elts[0] || 03100 density->get_centroid_x().get_max() < centroid->elts[0]) 03101 { 03102 ostringstream ost; 03103 ost << "Centroid-x " << centroid->elts[0] << " outside density range [" 03104 << density->get_centroid_x().get_min() << ',' 03105 << density->get_centroid_x().get_max() << ']'; 03106 throw Arg_error(ost.str()); 03107 } 03108 03109 if (density->get_centroid_y().get_min() > centroid->elts[1] || 03110 density->get_centroid_y().get_max() < centroid->elts[1]) 03111 { 03112 ostringstream ost; 03113 ost << "Centroid-y " << centroid->elts[1] << " outside density range [" 03114 << density->get_centroid_y().get_min() << ',' 03115 << density->get_centroid_y().get_max() << ']'; 03116 throw Arg_error(ost.str()); 03117 } 03118 03119 if (density->get_centroid_z().get_min() > centroid->elts[2] || 03120 density->get_centroid_z().get_max() < centroid->elts[2]) 03121 { 03122 ostringstream ost; 03123 ost << "Centroid-z " << centroid->elts[2] << " outside density range [" 03124 << density->get_centroid_z().get_min() << ',' 03125 << density->get_centroid_z().get_max() << ']'; 03126 throw Arg_error(ost.str()); 03127 } 03128 } 03129 03130 /* -------------------------------------------------------------------------- */ 03131 03132 03133 03134 03135 03136 03137 03138 03139 03140 03141 /* -------------------- Printed_apical_structure -------------------------- */ 03142 03167 Apical_structure* Printed_apical_structure::recursively_convert 03168 ( 03169 Structure* parent, 03170 std::list<class Printed_apical_structure*>::const_iterator apical_begin, 03171 std::list<class Printed_apical_structure*>::const_iterator apical_end, 03172 std::list<class Printed_lateral_structure*>::const_iterator lateral_begin, 03173 std::list<class Printed_lateral_structure*>::const_iterator lateral_end 03174 ) 03175 const throw (Arg_error) 03176 { 03177 Apical_structure* s = convert(parent); 03178 03179 try 03180 { 03181 if (apical) 03182 { 03183 bool found = false; 03184 for (list<Printed_apical_structure*>::const_iterator 03185 it = apical_begin; !found && it != apical_end; it++) 03186 { 03187 if ((*it)->get_id() == apical) 03188 { 03189 found = true; 03190 (*it)->recursively_convert(s, apical_begin, apical_end, 03191 lateral_begin, lateral_end); 03192 } 03193 } 03194 if (!found) 03195 { 03196 ostringstream ost; 03197 ost << "Failed converting printed spore " << id 03198 << ": Missing printed apical structure " << apical; 03199 throw Arg_error(ost.str()); 03200 } 03201 } 03202 03203 for (list<uint32_t>::const_iterator lateral = laterals.begin(); 03204 lateral != laterals.end(); lateral++) 03205 { 03206 bool found = false; 03207 for (list<Printed_lateral_structure*>::const_iterator 03208 it = lateral_begin; !found && it != lateral_end; it++) 03209 { 03210 if ((*it)->get_id() == *lateral) 03211 { 03212 found = true; 03213 (*it)->recursively_convert(s, apical_begin, apical_end, 03214 lateral_begin, lateral_end); 03215 } 03216 } 03217 if (!found) 03218 { 03219 ostringstream ost; 03220 ost << "Failed converting printed spore " << id 03221 << ": Missing printed lateral structure " << apical; 03222 throw Arg_error(ost.str()); 03223 } 03224 } 03225 } 03226 catch (Arg_error e) 03227 { 03228 if (parent) 03229 { 03230 parent->set_apical(0); 03231 } 03232 delete s; 03233 throw e; 03234 } 03235 03236 return s; 03237 } 03238 03239 /* -------------------------------------------------------------------------- */ 03240 03241 03242 03243 03244 03245 03246 03247 03248 03249 03250 /* ---------------------------- Lateral_structure ------------------------- */ 03251 03270 Lateral_structure::Lateral_structure 03271 ( 03272 float centroid_x, 03273 float centroid_y, 03274 float centroid_z, 03275 float lat_dist, 03276 float length, 03277 float width, 03278 float base_theta, 03279 float base_psi, 03280 float theta, 03281 float psi, 03282 float opacity, 03283 size_t level, 03284 const class Lateral_structure_density* density 03285 ) 03286 throw (Arg_error) 03287 : Structure(length, width, base_theta, base_psi, theta, psi, opacity, 03288 level, density) 03289 { 03290 this->lat_dist = lat_dist; 03291 this->density = density; 03292 03293 create_vector_f(¢roid, 3); 03294 centroid->elts[0] = centroid_x; 03295 centroid->elts[1] = centroid_y; 03296 centroid->elts[2] = centroid_z; 03297 03298 check_centroid(); 03299 check_lat_dist(); 03300 03301 update_R(); 03302 update_growth_dir_from_R(); 03303 update_begin_pt(); 03304 update_end_pt(); 03305 } 03306 03307 03323 Lateral_structure::Lateral_structure 03324 ( 03325 Structure* parent, 03326 float lat_dist, 03327 float length, 03328 float width, 03329 float base_theta, 03330 float base_psi, 03331 float theta, 03332 float psi, 03333 float opacity, 03334 const class Lateral_structure_density* density 03335 ) 03336 throw (Arg_error) 03337 : Structure(length, width, base_theta, base_psi, theta, psi, opacity, 03338 parent->level+1, density) 03339 { 03340 this->parent = parent; 03341 this->lat_dist = lat_dist; 03342 this->density = density; 03343 03344 check_lat_dist(); 03345 03346 multiply_vector_by_scalar_f(&begin_pt, parent->growth_dir, 03347 parent->length*lat_dist); 03348 add_vectors_f(&begin_pt, begin_pt, parent->begin_pt); 03349 03350 update_R(); 03351 update_growth_dir_from_R(); 03352 update_centroid(); 03353 update_end_pt(); 03354 03355 parent->laterals.push_back(this); 03356 } 03357 03358 03360 Lateral_structure::Lateral_structure(const Lateral_structure& s) : Structure(s) 03361 { 03362 density = s.density; 03363 lat_dist = s.lat_dist; 03364 } 03365 03366 03368 Lateral_structure* Lateral_structure::recursively_clone() const 03369 { 03370 Lateral_structure* s = clone(); 03371 03372 s->apical = 0; 03373 s->laterals.clear(); 03374 03375 if (apical) 03376 { 03377 s->apical = apical->recursively_clone(); 03378 s->apical->parent = s; 03379 } 03380 for (list<Lateral_structure*>::const_iterator it = laterals.begin(); 03381 it != laterals.end(); it++) 03382 { 03383 Lateral_structure* lateral = (*it)->recursively_clone(); 03384 s->laterals.push_back(lateral); 03385 lateral->parent = s; 03386 } 03387 03388 return s; 03389 } 03390 03391 03397 Lateral_structure& Lateral_structure::operator= (const Lateral_structure& s) 03398 { 03399 Structure::operator=(s); 03400 03401 density = s.density; 03402 lat_dist = s.lat_dist; 03403 03404 return *this; 03405 } 03406 03407 03415 void Lateral_structure::set_parent(Structure* parent, float lat_dist) 03416 throw (Arg_error) 03417 { 03418 static int entry = 0; 03419 03420 entry++; 03421 03422 Structure* old_parent = this->parent; 03423 float old_lat_dist = this->lat_dist; 03424 03425 try 03426 { 03427 if (old_parent) 03428 { 03429 old_parent->remove_lateral(this); 03430 } 03431 } 03432 catch (Arg_error e) 03433 { 03434 std::cerr << "BUG: Lateral_structure::set_parent: " << e.get_msg() 03435 << '\n'; 03436 assert(0); 03437 } 03438 03439 try 03440 { 03441 this->parent = parent; 03442 this->lat_dist = lat_dist; 03443 03444 if (!parent) 03445 { 03446 check_lat_dist(); 03447 update_ancestry_log_prob(); 03448 return; 03449 } 03450 03451 parent->add_lateral(this); 03452 03453 check_lat_dist(); 03454 03455 multiply_vector_by_scalar_f(&begin_pt, parent->growth_dir, 03456 parent->length*lat_dist); 03457 add_vectors_f(&begin_pt, begin_pt, parent->begin_pt); 03458 03459 update_growth_dir_and_length_from_pts(); 03460 update_angles(); 03461 update_R(); 03462 update_centroid(); 03463 if (apical) 03464 { 03465 apical->update_from_parent_end_pt(); 03466 } 03467 update_laterals(); 03468 update_ancestry_log_prob(); 03469 } 03470 catch (Arg_error e) 03471 { 03472 if (entry < 2) 03473 { 03474 set_parent(old_parent, old_lat_dist); 03475 } 03476 else 03477 { 03478 // TODO the length has been coming up wrong because of precision. 03479 // Probably could throw something like Result_error exception 03480 // here. 03481 entry = 0; 03482 } 03483 throw e; 03484 } 03485 03486 entry = 0; 03487 } 03488 03489 03497 void Lateral_structure::set_lat_dist(float lat_dist) throw (Arg_error) 03498 { 03499 static int entry = 0; 03500 03501 entry++; 03502 03503 float old_lat_dist = this->lat_dist; 03504 03505 try 03506 { 03507 this->lat_dist = lat_dist; 03508 03509 check_lat_dist(); 03510 03511 if (!parent) 03512 return; 03513 03514 multiply_vector_by_scalar_f(&begin_pt, parent->growth_dir, 03515 parent->length*lat_dist); 03516 add_vectors_f(&begin_pt, begin_pt, parent->begin_pt); 03517 03518 update_growth_dir_and_length_from_pts(); 03519 update_angles(); 03520 update_R(); 03521 update_centroid(); 03522 if (apical) 03523 { 03524 apical->update_from_parent_end_pt(); 03525 } 03526 update_laterals(); 03527 update_ancestry_log_prob(); 03528 } 03529 catch (Arg_error e) 03530 { 03531 if (entry < 2) 03532 { 03533 set_lat_dist(old_lat_dist); 03534 } 03535 else 03536 { 03537 // TODO the length has been coming up wrong because of precision. 03538 // Probably could throw something like Result_error exception 03539 // here. 03540 entry = 0; 03541 } 03542 throw e; 03543 } 03544 03545 entry = 0; 03546 } 03547 03548 03574 void Lateral_structure::print(ostream& out) const 03575 { 03576 Structure::print(out); 03577 03578 out << " Lat Dist: " << lat_dist << '\n'; 03579 } 03580 03581 03582 /* 03583 * @throw jwscxx::base::Arg_error Apical_structure values are not in the 03584 * density parameter range. 03585 */ 03586 void Lateral_structure::update_from_parent_end_pt() throw (Arg_error) 03587 { 03588 assert(parent); 03589 03590 multiply_vector_by_scalar_f(&begin_pt, parent->growth_dir, 03591 parent->length*lat_dist); 03592 add_vectors_f(&begin_pt, begin_pt, parent->begin_pt); 03593 03594 update_growth_dir_and_length_from_pts(); 03595 update_angles(); 03596 update_R(); 03597 update_centroid(); 03598 if (apical) 03599 { 03600 apical->update_from_parent_end_pt(); 03601 } 03602 update_laterals(); 03603 03604 update_log_prob(); 03605 } 03606 03607 03609 void Lateral_structure::update_log_prob() 03610 { 03611 float mu, sigma; 03612 float min, max; 03613 double delta; 03614 double p_1, p_2; 03615 03616 Structure::update_log_prob(); 03617 03618 /* Centroid_x */ 03619 min = density->get_centroid_x().get_min(); 03620 max = density->get_centroid_x().get_max(); 03621 log_prob -= log(max - min); 03622 03623 /* Centroid_y */ 03624 min = density->get_centroid_y().get_min(); 03625 max = density->get_centroid_y().get_max(); 03626 log_prob -= log(max - min); 03627 03628 /* Centroid_x */ 03629 min = density->get_centroid_z().get_min(); 03630 max = density->get_centroid_z().get_max(); 03631 log_prob -= log(max - min); 03632 03633 /* Lateral distance */ 03634 mu = density->get_lat_dist().get_mu(); 03635 sigma = density->get_lat_dist().get_sigma(); 03636 min = density->get_lat_dist().get_min(); 03637 max = density->get_lat_dist().get_max(); 03638 delta = (max - min) / 1000; 03639 p_1 = integrate_gaussian_pdf_d(mu, sigma, lat_dist, lat_dist+delta); 03640 p_2 = integrate_gaussian_pdf_d(mu, sigma, min, max); 03641 log_prob += log((p_1 < JWSC_MIN_LOG_ARG) ? JWSC_MIN_LOG_ARG : p_1); 03642 log_prob -= log((p_2 < JWSC_MIN_LOG_ARG) ? JWSC_MIN_LOG_ARG : p_2); 03643 03644 #if defined ALTERNARIA_HAVE_ISINF && defined ALTERNARIA_HAVE_ISNAN 03645 assert(!std::isinf(log_prob) && !std::isnan(log_prob)); 03646 #endif 03647 } 03648 03649 03654 void Lateral_structure::check_centroid() const throw (Arg_error) 03655 { 03656 if (density->get_centroid_x().get_min() > centroid->elts[0] || 03657 density->get_centroid_x().get_max() < centroid->elts[0]) 03658 { 03659 ostringstream ost; 03660 ost << "Centroid-x " << centroid->elts[0] << " outside density range [" 03661 << density->get_centroid_x().get_min() << ',' 03662 << density->get_centroid_x().get_max() << ']'; 03663 throw Arg_error(ost.str()); 03664 } 03665 03666 if (density->get_centroid_y().get_min() > centroid->elts[1] || 03667 density->get_centroid_y().get_max() < centroid->elts[1]) 03668 { 03669 ostringstream ost; 03670 ost << "Centroid-y " << centroid->elts[1] << " outside density range [" 03671 << density->get_centroid_y().get_min() << ',' 03672 << density->get_centroid_y().get_max() << ']'; 03673 throw Arg_error(ost.str()); 03674 } 03675 03676 if (density->get_centroid_z().get_min() > centroid->elts[2] || 03677 density->get_centroid_z().get_max() < centroid->elts[2]) 03678 { 03679 ostringstream ost; 03680 ost << "Centroid-z " << centroid->elts[2] << " outside density range [" 03681 << density->get_centroid_z().get_min() << ',' 03682 << density->get_centroid_z().get_max() << ']'; 03683 throw Arg_error(ost.str()); 03684 } 03685 } 03686 03687 03692 void Lateral_structure::check_lat_dist() const throw (Arg_error) 03693 { 03694 if (density->get_lat_dist().get_min() > lat_dist || 03695 density->get_lat_dist().get_max() < lat_dist) 03696 { 03697 ostringstream ost; 03698 ost << "Lateral distance " << lat_dist << " outside density range [" 03699 << density->get_lat_dist().get_min() << ',' 03700 << density->get_lat_dist().get_max() << ']'; 03701 throw Arg_error(ost.str()); 03702 } 03703 } 03704 03705 /* -------------------------------------------------------------------------- */ 03706 03707 03708 03709 03710 03711 03712 03713 /* -------------------- Printed_lateral_structure ------------------------- */ 03714 03722 void Printed_lateral_structure::read_lat_dist(std::istream& in) 03723 throw (IO_error, Arg_error) 03724 { 03725 const char* member_value; 03726 03727 if (!(member_value = Structure::get_member_value("Lat Dist", in))) 03728 { 03729 throw Arg_error("Missing lateral distance"); 03730 } 03731 istringstream ist(member_value); 03732 ist >> lat_dist; 03733 if (ist.fail()) 03734 { 03735 throw Arg_error("Invalid lateral distance"); 03736 } 03737 } 03738 03739 03764 Lateral_structure* Printed_lateral_structure::recursively_convert 03765 ( 03766 Structure* parent, 03767 std::list<class Printed_apical_structure*>::const_iterator apical_begin, 03768 std::list<class Printed_apical_structure*>::const_iterator apical_end, 03769 std::list<class Printed_lateral_structure*>::const_iterator lateral_begin, 03770 std::list<class Printed_lateral_structure*>::const_iterator lateral_end 03771 ) 03772 const throw (Arg_error) 03773 { 03774 Lateral_structure* s = convert(parent); 03775 03776 try 03777 { 03778 if (apical) 03779 { 03780 bool found = false; 03781 for (list<Printed_apical_structure*>::const_iterator 03782 it = apical_begin; !found && it != apical_end; it++) 03783 { 03784 if ((*it)->get_id() == apical) 03785 { 03786 found = true; 03787 (*it)->recursively_convert(s, apical_begin, apical_end, 03788 lateral_begin, lateral_end); 03789 } 03790 } 03791 if (!found) 03792 { 03793 ostringstream ost; 03794 ost << "Failed converting printed spore " << id 03795 << ": Missing printed apical structure " << apical; 03796 throw Arg_error(ost.str()); 03797 } 03798 } 03799 03800 for (list<uint32_t>::const_iterator lateral = laterals.begin(); 03801 lateral != laterals.end(); lateral++) 03802 { 03803 bool found = false; 03804 for (list<Printed_lateral_structure*>::const_iterator 03805 it = lateral_begin; !found && it != lateral_end; it++) 03806 { 03807 if ((*it)->get_id() == *lateral) 03808 { 03809 found = true; 03810 (*it)->recursively_convert(s, apical_begin, apical_end, 03811 lateral_begin, lateral_end); 03812 } 03813 } 03814 if (!found) 03815 { 03816 ostringstream ost; 03817 ost << "Failed converting printed spore " << id 03818 << ": Missing printed lateral structure " << apical; 03819 throw Arg_error(ost.str()); 03820 } 03821 } 03822 } 03823 catch (Arg_error e) 03824 { 03825 if (parent) 03826 { 03827 parent->remove_lateral(s); 03828 } 03829 delete s; 03830 throw e; 03831 } 03832 03833 return s; 03834 } 03835 03836 /* -------------------------------------------------------------------------- */