Alternaria
fit cylinders and ellipsoids to fungus
structure.cpp
Go to the documentation of this file.
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(&centroid, 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(&centroid, 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(&centroid, growth_dir, 0.5f*length);
01312     add_vectors_f(&centroid, 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(&centroid, 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(&centroid, 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(&centroid, 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 /* -------------------------------------------------------------------------- */