Alternaria
fit cylinders and ellipsoids to fungus
spore.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 #include <cmath>
00049 #include <cstring>
00050 #include <cassert>
00051 #include <iostream>
00052 #include <sstream>
00053 #include <list>
00054 #include <vector>
00055 
00056 #include <inttypes.h>
00057 
00058 #if defined ALTERNARIA_HAVE_OPENGL_FRAMEWORK
00059 #include <OpenGL/gl.h>
00060 #include <OpenGL/glu.h>
00061 #elif defined ALTERNARIA_HAVE_OPENGL
00062 #include <GL/gl.h>
00063 #include <GL/glu.h>
00064 #endif
00065 
00066 #include <jwsc/base/limits.h>
00067 #include <jwsc/math/constants.h>
00068 #include <jwsc/prob/pdf.h>
00069 #include <jwsc/vector/vector.h>
00070 #include <jwsc/vector/vector_math.h>
00071 #include <jwsc/matrix/matrix.h>
00072 #include <jwsc/matrix/matrix_math.h>
00073 #include <jwsc/matblock/matblock.h>
00074 
00075 #include "density.h"
00076 #include "printable.h"
00077 #include "structure.h"
00078 #include "dd_spore.h"
00079 #include "hypha.h"
00080 #include "spore.h"
00081 
00082 
00083 #define  CENTROID_X_MIN  0
00084 #define  CENTROID_X_MAX  0
00085 
00086 #define  CENTROID_Y_MIN  0
00087 #define  CENTROID_Y_MAX  0
00088 
00089 #define  CENTROID_Z_MIN  0
00090 #define  CENTROID_Z_MAX  0
00091 
00092 #define  LENGTH_MU       40.0f
00093 #define  LENGTH_SIGMA    4.0f
00094 #define  LENGTH_MIN      10.f
00095 #define  LENGTH_MAX      100.0f
00096 
00097 #define  WIDTH_MU        15.0f
00098 #define  WIDTH_SIGMA     1.0f
00099 #define  WIDTH_MIN       2.0f
00100 #define  WIDTH_MAX       30.0f
00101 
00102 #define  THETA_MU        0
00103 #define  THETA_SIGMA     0.2f
00104 #define  THETA_MIN       0
00105 #define  THETA_MAX       JWSC_PI_2
00106 
00107 #define  PSI_MIN         -JWSC_PI
00108 #define  PSI_MAX         JWSC_PI
00109 
00110 #define  OPACITY_MU      0.9f
00111 #define  OPACITY_SIGMA   0.2f
00112 #define  OPACITY_MIN     0.1f
00113 #define  OPACITY_MAX     1.0f
00114 
00115 
00116 using std::istream;
00117 using std::ostringstream;
00118 using std::strncmp;
00119 using std::strlen;
00120 using std::list;
00121 using std::vector;
00122 using namespace jwsc;
00123 using jwscxx::base::Arg_error;
00124 using jwscxx::base::IO_error;
00125 
00126 
00127 /* ----------------------------  Spore_density  ----------------------------- */
00128 
00138 Spore_density::Spore_density(const DD_spore_set* dd_spores) throw (Arg_error)
00139 {
00140     float mu, sigma;
00141     float min, max;
00142 
00143     min = CENTROID_X_MIN;
00144     max = CENTROID_X_MAX;
00145     set_centroid_x(min, max);
00146 
00147     min = CENTROID_Y_MIN;
00148     max = CENTROID_Y_MAX;
00149     set_centroid_y(min, max);
00150 
00151     min = CENTROID_Z_MIN;
00152     max = CENTROID_Z_MAX;
00153     set_centroid_z(min, max);
00154 
00155     mu    = LENGTH_MU;
00156     sigma = LENGTH_SIGMA;
00157     min   = LENGTH_MIN;
00158     max   = LENGTH_MAX;
00159     set_length(mu, sigma, min, max);
00160 
00161     mu    = WIDTH_MU;
00162     sigma = WIDTH_SIGMA;
00163     min   = WIDTH_MIN;
00164     max   = WIDTH_MAX;
00165     set_width(mu, sigma, min, max);
00166 
00167     mu    = THETA_MU;
00168     sigma = THETA_SIGMA;
00169     min   = THETA_MIN;
00170     max   = THETA_MAX;
00171     set_theta(mu, sigma, min, max);
00172 
00173     min = PSI_MIN;
00174     max = PSI_MAX;
00175     set_psi(min, max);
00176 
00177     mu    = OPACITY_MU;
00178     sigma = OPACITY_SIGMA;
00179     min   = OPACITY_MIN;
00180     max   = OPACITY_MAX;
00181     set_opacity(mu, sigma, min, max);
00182 
00183     this->dd_spores = dd_spores;
00184 }
00185 
00186 
00188 Spore_density* Spore_density::clone() const
00189 {
00190     float mu, sigma;
00191     float min, max;
00192 
00193     Spore_density* s  = new Spore_density();
00194 
00195     min = centroid_x.get_min();
00196     max = centroid_x.get_max();
00197     s->set_centroid_x(min, max);
00198 
00199     min = centroid_y.get_min();
00200     max = centroid_y.get_max();
00201     s->set_centroid_y(min, max);
00202 
00203     min = centroid_z.get_min();
00204     max = centroid_z.get_max();
00205     s->set_centroid_z(min, max);
00206 
00207     mu    = length.get_mu();
00208     sigma = length.get_sigma();
00209     min   = length.get_min();
00210     max   = length.get_max();
00211     s->set_length(mu, sigma, min, max);
00212 
00213     mu    = width.get_mu();
00214     sigma = width.get_sigma();
00215     min   = width.get_min();
00216     max   = width.get_max();
00217     s->set_width(mu, sigma, min, max);
00218 
00219     mu    = theta.get_mu();
00220     sigma = theta.get_sigma();
00221     min   = theta.get_min();
00222     max   = theta.get_max();
00223     s->set_theta(mu, sigma, min, max);
00224 
00225     min = psi.get_min();
00226     max = psi.get_max();
00227     s->set_psi(min, max);
00228 
00229     mu    = opacity.get_mu();
00230     sigma = opacity.get_sigma();
00231     min   = opacity.get_min();
00232     max   = opacity.get_max();
00233     s->set_opacity(mu, sigma, min, max);
00234 
00235     return s;
00236 }
00237 
00238 
00246 Spore* Spore_density::sample(float base_theta, float base_psi, size_t level) 
00247     const
00248 {
00249     return new Spore(sample_centroid_x(), sample_centroid_y(), 
00250             sample_centroid_z(), sample_length(), sample_width(), base_theta, 
00251             base_psi, sample_theta(), sample_psi(), sample_opacity(), level,
00252             this);
00253 }
00254 
00255 
00269 Spore* Spore_density::sample
00270 (
00271     float centroid_x, 
00272     float centroid_y, 
00273     float centroid_z,
00274     float base_theta,
00275     float base_psi,
00276     size_t level
00277 ) 
00278 const throw (Arg_error)
00279 {
00280     return new Spore(centroid_x, centroid_y, centroid_z, sample_length(), 
00281             sample_width(), base_theta, base_psi, sample_theta(), sample_psi(), 
00282             sample_opacity(), level, this);
00283 }
00284 
00285 
00296 Spore* Spore_density::sample
00297 (
00298     Structure* parent,
00299     float      base_theta,
00300     float      base_psi
00301 ) 
00302 const throw (Arg_error)
00303 {
00304     if (dd_spores)
00305     {
00306         return dd_spores->propose_similar_spore(parent, base_theta, base_psi, 
00307                 this, 0);
00308     }
00309 
00310     return new Spore(parent, sample_length(), sample_width(), base_theta,
00311             base_psi, sample_theta(), sample_psi(), sample_opacity(), this);
00312 }
00313 
00314 /* -------------------------------------------------------------------------- */
00315 
00316 
00317 
00318 
00319 
00320 
00321 /* --------------------------------  Spore  --------------------------------- */
00322 
00340 Spore::Spore
00341 (
00342     float centroid_x, 
00343     float centroid_y,
00344     float centroid_z,
00345     float length,
00346     float width,
00347     float base_theta,
00348     float base_psi,
00349     float theta,
00350     float psi,
00351     float opacity,
00352     size_t level,
00353     const class Spore_density* density
00354 ) 
00355 throw (Arg_error)
00356     : Apical_structure(centroid_x, centroid_y, centroid_z, length, width, 
00357             base_theta, base_psi, theta, psi, opacity, level, density)
00358 {
00359     this->density = density;
00360 
00361     update_ancestry_log_prob();
00362 }
00363 
00364 
00380 Spore::Spore
00381 (
00382     Structure* parent,
00383     float      length,
00384     float      width,
00385     float      base_theta,
00386     float      base_psi,
00387     float      theta,
00388     float      psi,
00389     float      opacity,
00390     const class Spore_density* density
00391 )
00392 throw (Arg_error, Apical_error)
00393     : Apical_structure(parent, length, width, base_theta, base_psi, theta, psi, 
00394             opacity, density)
00395 {
00396     this->density = density;
00397 
00398     update_ancestry_log_prob();
00399 }
00400 
00401 
00418 Spore::Spore
00419 (
00420     Structure* parent,
00421     float      centroid_x, 
00422     float      centroid_y,
00423     float      centroid_z,
00424     float      length,
00425     float      width,
00426     float      base_theta,
00427     float      base_psi,
00428     float      opacity,
00429     const class Spore_density* density
00430 )
00431 throw (Arg_error, Apical_error)
00432     : Apical_structure(parent, centroid_x, centroid_y, centroid_z, length, 
00433             width, base_theta, base_psi, opacity, density)
00434 {
00435     this->density = density;
00436 
00437     update_ancestry_log_prob();
00438 }
00439 
00440 
00442 Spore::Spore(const Spore& s) : Apical_structure(s)
00443 {
00444     density = s.density;
00445 }
00446 
00447 
00449 Spore::Spore
00450 (
00451     const class Apical_hypha& h, 
00452     float                     width, 
00453     const Spore_density*      density
00454 ) 
00455 throw (Arg_error) : Apical_structure(h)
00456 {
00457     Structure::density        = density;
00458     Apical_structure::density = density;
00459     this->density             = density;
00460 
00461     this->width               = width;
00462 
00463     try
00464     {
00465         check_width();
00466         check_length();
00467         check_theta();
00468         check_psi();
00469         check_opacity();
00470     }
00471     catch (Arg_error e)
00472     {
00473         apical = 0;
00474         laterals.clear();
00475         throw e;
00476     }
00477 
00478     update_log_prob();
00479 }
00480 
00481 
00483 Spore* Spore::clone() const
00484 {
00485     return new Spore(*this);
00486 }
00487 
00488 
00494 Spore& Spore::operator= (const Spore& s)
00495 {
00496     Apical_structure::operator=(s);
00497 
00498     density = s.density;
00499 
00500     return *this;
00501 }
00502 
00503 
00514 Spore* Spore::split_into_apical
00515 (
00516     const Spore* rvals_1,
00517     const Spore* rvals_2
00518 ) 
00519 throw (Arg_error)
00520 {
00521     return (Spore*)Apical_structure::split_into_apical(rvals_1, rvals_2);
00522 }
00523 
00524 
00539 Spore* Spore::merge_with_apical
00540 (
00541     const Spore* rvals
00542 ) 
00543 throw (Arg_error)
00544 {
00545     if (!apical)
00546     {
00547         throw Arg_error("No apical to merge with");
00548     }
00549 
00550     if (!dynamic_cast<Spore*>(apical))
00551     {
00552         throw Arg_error("Apical to merge with not a spore");
00553     }
00554 
00555     return (Spore*)Apical_structure::merge_with_apical(rvals);
00556 }
00557 
00558 
00573 class Apical_hypha* Spore::split_into_apical
00574 (
00575     const Apical_hypha* rvals_1,
00576     const Apical_hypha* rvals_2
00577 ) 
00578 throw (Arg_error)
00579 {
00580     Apical_hypha* split = new Apical_hypha(*this, rvals_1->get_width(),
00581             rvals_1->get_density());
00582 
00583     try
00584     {
00585         this->replace(split);
00586     }
00587     catch (Arg_error e)
00588     {
00589         delete split;
00590         throw e;
00591     }
00592 
00593     try
00594     {
00595         split->split_into_apical(rvals_1, rvals_2);
00596     }
00597     catch (Arg_error e)
00598     {
00599         split->replace(this);
00600         delete split;
00601         throw e;
00602     }
00603 
00604     return split;
00605 }
00606 
00607 
00613 void Spore::replace(class Apical_hypha* hypha) throw (Arg_error)
00614 {
00615     Apical_structure::replace(hypha);
00616 }
00617 
00618 
00659 bool Spore::draw_in_matrix_f
00660 (
00661      jwsc::Matrix_f* M, 
00662      float     x, 
00663      float     y,
00664      float     z,
00665      float     x_scale,
00666      float     y_scale,
00667      float     z_scale,
00668      bool      fill
00669 ) 
00670 const
00671 {
00672     uint32_t num_rows;
00673     uint32_t num_cols;
00674     uint32_t row, col;
00675     int64_t  row2, col2;
00676 
00677     float center;
00678     float x_pad;
00679     float y_pad;
00680 
00681     Vector_f* C  = 0;
00682     Matrix_f* M2 = 0;
00683 
00684     /* Create a sub-matrix with just the spore in it. */
00685     center = (width > length) ? width : length;
00686 
00687     x_pad = 3*x_scale;
00688     y_pad = 3*y_scale;
00689 
00690     create_vector_f(&C, 3);
00691     C->elts[0] = center + x_pad;
00692     C->elts[1] = center + y_pad;
00693     C->elts[2] = centroid->elts[2];
00694 
00695     // Copy this spore.
00696     Spore spore(*this);
00697 
00698     // Position the copy in the center.
00699     subtract_vectors_f(&C, C, spore.centroid);
00700     add_vectors_f(&(spore.begin_pt), spore.begin_pt, C);
00701     add_vectors_f(&(spore.centroid), spore.centroid, C);
00702     add_vectors_f(&(spore.end_pt), spore.end_pt, C);
00703 
00704     free_vector_f(C);
00705 
00706     // Clear the laterals and the apical so deleting the copy doesn't mess
00707     // things up.
00708     spore.apical = 0;
00709     spore.laterals.clear();
00710 
00711     num_rows = static_cast<uint32_t>(std::floor((2 * (center+y_pad)) / 
00712             y_scale + 0.5));
00713     num_cols = static_cast<uint32_t>(std::floor((2 * (center+x_pad)) / 
00714             x_scale + 0.5));
00715 
00716     create_zero_matrix_f(&M2, num_rows, num_cols);
00717 
00718     spore.draw_in_zeroed_matrix_f(M2, 0, 0, z, x_scale, y_scale, z_scale, fill);
00719 
00720     bool intersect = false;
00721 
00722     /* Copy the sub-matrix back into the target matrix. */
00723     row2 = static_cast<int64_t>(floor(
00724                 (centroid->elts[1] - (center+y_pad) - y) / y_scale + 0.5));
00725 
00726     for (row = 0; row < num_rows; row++)
00727     {
00728         col2 = static_cast<int64_t>(floor(
00729                     (centroid->elts[0] - (center+x_pad) - x) / x_scale + 0.5));
00730 
00731         for (col = 0; col < num_cols; col++)
00732         {
00733             if ((col2 >= 0) && (col2 < M->num_cols) && 
00734                 (row2 >= 0) && (row2 < M->num_rows))
00735             {
00736                 if (M2->elts[ row ][ col ] > 0)
00737                 {
00738                     uint32_t current_id = (uint32_t)floor(
00739                             M->elts[ row2 ][ col2 ]);
00740 
00741                     if (current_id > 0 && current_id != id && 
00742                             !has_child_id(current_id))
00743                     {
00744                         intersect = true;
00745                     }
00746 
00747                     M->elts[ row2 ][ col2 ] = M2->elts[ row ][ col ];
00748                 }
00749             }
00750             col2++;
00751         }
00752         row2++; 
00753     }
00754 
00755     free_matrix_f(M2);
00756 
00757     return intersect;
00758 }
00759 
00760 
00805 bool Spore::draw_in_matblock_f
00806 (
00807      jwsc::Matblock_f* M_blk, 
00808      float       x, 
00809      float       y,
00810      float       z,
00811      float       x_scale,
00812      float       y_scale,
00813      float       z_scale,
00814      bool        fill
00815 )
00816 const
00817 {
00818     uint32_t num_mats;
00819     uint32_t mat;
00820 
00821     double mat_z;
00822 
00823     Matrix_f* M = 0;
00824 
00825     num_mats  = M_blk->num_mats;
00826     mat_z     = z;
00827 
00828     bool intersect = false;
00829 
00830     for (mat = 0; mat < num_mats; mat++)
00831     {
00832         mat_z = z + mat*z_scale;
00833 
00834         copy_matrix_from_matblock_f(&M, M_blk, MATBLOCK_MAT_MATRIX, mat);
00835         if (draw_in_matrix_f(M, x, y, mat_z, x_scale, y_scale, z_scale, fill))
00836         {
00837             intersect = true;
00838         }
00839         copy_matrix_into_matblock_f(&M_blk, M_blk, M, MATBLOCK_MAT_MATRIX, mat);
00840     }
00841 
00842     free_matrix_f(M);
00843 
00844     return intersect;
00845 }
00846 
00847 
00888 void Spore::draw_in_zeroed_matrix_f
00889 (
00890      jwsc::Matrix_f* M, 
00891      float     x, 
00892      float     y,
00893      float     z,
00894      float     x_scale,
00895      float     y_scale,
00896      float     z_scale,
00897      bool      fill
00898 ) 
00899 const
00900 {
00901     uint32_t num_rows;
00902     uint32_t num_cols;
00903     uint32_t row, col;
00904     uint32_t left_edge;
00905     uint32_t middle;
00906     uint32_t elements_to_fill;
00907     uint32_t begin_fill_col;
00908     uint32_t end_fill_col;
00909 
00910     float minor, major;
00911     float M_x, M_y, M_z;
00912     float d, d_prev;
00913 
00914     Matrix_f* R_inv       = 0;
00915     Vector_f* point_world = 0;
00916     Vector_f* point_spore = 0;
00917 
00918     num_rows = M->num_rows;
00919     num_cols = M->num_cols;
00920 
00921     minor = 0.5*width;
00922     major = 0.5*length;
00923 
00924     /* Inverse rotation matrix. */
00925     transpose_matrix_f(&R_inv, R);
00926 
00927     create_vector_f(&point_world, 3);
00928     create_vector_f(&point_spore, 3);
00929 
00930     for (row = 0; row < num_rows; row++)
00931     {
00932         /* Get coordinates of matrix element in world units. Note that we
00933          * are using the center of matrix elements for position. */
00934         point_world->elts[ 0 ] = x + x_scale*((-1) + 0.5);
00935         point_world->elts[ 1 ] = y + y_scale*(row + 0.5);
00936         point_world->elts[ 2 ] = z + z_scale*0.5;
00937 
00938         /* Translate matrix element and ... */
00939         point_world->elts[ 0 ] -= centroid->elts[0];
00940         point_world->elts[ 1 ] -= centroid->elts[1];
00941         point_world->elts[ 2 ] -= centroid->elts[2];
00942 
00943         /* Rotate matrix element to spore space. */
00944         multiply_matrix_and_vector_f(&point_spore, R_inv, point_world);
00945 
00946         M_x = point_spore->elts[ 0 ];
00947         M_y = point_spore->elts[ 1 ];
00948         M_z = point_spore->elts[ 2 ];
00949 
00950         d_prev = (M_x*M_x)/(minor*minor) + 
00951                  (M_y*M_y)/(minor*minor) + 
00952                  (M_z*M_z)/(major*major);
00953 
00954         for (col = 0; col < num_cols; col++)
00955         {
00956             /* Get coordinates of matrix element in world units. Note that we
00957              * are using the center of matrix elements for position. */
00958             point_world->elts[ 0 ] = x + x_scale*(col + 0.5);
00959             point_world->elts[ 1 ] = y + y_scale*(row + 0.5);
00960             point_world->elts[ 2 ] = z + z_scale*0.5;
00961 
00962             /* Translate matrix element and ... */
00963             point_world->elts[ 0 ] -= centroid->elts[0];
00964             point_world->elts[ 1 ] -= centroid->elts[1];
00965             point_world->elts[ 2 ] -= centroid->elts[2];
00966 
00967             /* Rotate matrix element to spore space. */
00968             multiply_matrix_and_vector_f(&point_spore, R_inv, point_world);
00969 
00970             M_x = point_spore->elts[ 0 ];
00971             M_y = point_spore->elts[ 1 ];
00972             M_z = point_spore->elts[ 2 ];
00973 
00974             d = (M_x*M_x)/(minor*minor) + 
00975                 (M_y*M_y)/(minor*minor) + 
00976                 (M_z*M_z)/(major*major);
00977 
00978             if (((d - 1.0) <= 0 && (d_prev - 1.0) >= 0) ||
00979                 ((d - 1.0) >= 0 && (d_prev - 1.0) <= 0))
00980             {
00981                 M->elts[ row ][ col ] = id + opacity;
00982             }
00983 
00984             d_prev = d;
00985         }
00986     }
00987     for (col = 0; col < num_cols; col++)
00988     {
00989         /* Get coordinates of matrix element in world units. Note that we
00990          * are using the center of matrix elements for position. */
00991         point_world->elts[ 0 ] = x + x_scale*(col + 0.5);
00992         point_world->elts[ 1 ] = y + y_scale*((-1) + 0.5);
00993         point_world->elts[ 2 ] = z + z_scale*0.5;
00994 
00995         /* Translate matrix element and ... */
00996         point_world->elts[ 0 ] -= centroid->elts[0];
00997         point_world->elts[ 1 ] -= centroid->elts[1];
00998         point_world->elts[ 2 ] -= centroid->elts[2];
00999 
01000         /* Rotate matrix element to spore space. */
01001         multiply_matrix_and_vector_f(&point_spore, R_inv, point_world);
01002 
01003         M_x = point_spore->elts[ 0 ];
01004         M_y = point_spore->elts[ 1 ];
01005         M_z = point_spore->elts[ 2 ];
01006 
01007         d_prev = (M_x*M_x)/(minor*minor) + 
01008                  (M_y*M_y)/(minor*minor) + 
01009                  (M_z*M_z)/(major*major);
01010 
01011         for (row = 0; row < num_rows; row++)
01012         {
01013             /* Get coordinates of matrix element in world units. Note that we
01014              * are using the center of matrix elements for position. */
01015             point_world->elts[ 0 ] = x + x_scale*(col + 0.5);
01016             point_world->elts[ 1 ] = y + y_scale*(row + 0.5);
01017             point_world->elts[ 2 ] = z + z_scale*0.5;
01018 
01019             /* Translate matrix element and ... */
01020             point_world->elts[ 0 ] -= centroid->elts[0];
01021             point_world->elts[ 1 ] -= centroid->elts[1];
01022             point_world->elts[ 2 ] -= centroid->elts[2];
01023 
01024             /* Rotate matrix element to spore space. */
01025             multiply_matrix_and_vector_f(&point_spore, R_inv, point_world);
01026 
01027             M_x = point_spore->elts[ 0 ];
01028             M_y = point_spore->elts[ 1 ];
01029             M_z = point_spore->elts[ 2 ];
01030 
01031             d = (M_x*M_x)/(minor*minor) + 
01032                 (M_y*M_y)/(minor*minor) + 
01033                 (M_z*M_z)/(major*major);
01034 
01035             if (((d - 1.0) <= 0 && (d_prev - 1.0) >= 0) ||
01036                 ((d - 1.0) >= 0 && (d_prev - 1.0) <= 0))
01037             {
01038                 M->elts[ row ][ col ] = id + opacity;
01039             }
01040 
01041             d_prev = d;
01042         }
01043     }
01044 
01045     /* Fill in the spore. */
01046     if (fill)
01047     {
01048         for (row = 0; row < num_rows; row++)
01049         {
01050             left_edge        = 0;
01051             middle           = 0;
01052             elements_to_fill = 0;
01053             begin_fill_col   = 0;
01054             end_fill_col     = 0;
01055 
01056             for (col = 0; col < num_cols; col++)
01057             {
01058                 if (left_edge && (M->elts[ row ][ col ] == 0))
01059                 {
01060                     left_edge = 0;
01061                     middle = 1;
01062                     begin_fill_col = col;
01063                 }
01064                 else if (middle && (M->elts[ row ][ col ] > 0))
01065                 {
01066                     elements_to_fill = 1;
01067                     end_fill_col = col;
01068                 }
01069                 else if (M->elts[ row ][ col ] > 0)
01070                 {
01071                     left_edge = 1;
01072                 }
01073             }
01074 
01075             if (elements_to_fill)
01076             {
01077                 for (col = begin_fill_col; col < end_fill_col; col++)
01078                 {
01079                     M->elts[ row ][ col ] = id + opacity;
01080                 }
01081             }
01082         }
01083     }
01084 
01085     free_vector_f(point_world);
01086     free_vector_f(point_spore);
01087     free_matrix_f(R_inv);
01088 }
01089 
01090 
01095 #if defined ALTERNARIA_HAVE_OPENGL_FRAMEWORK || defined ALTERNARIA_HAVE_OPENGL
01096 void Spore::draw_in_opengl(GLUquadric* quad, float scale) const
01097 {
01098     static GLfloat amb_dif[4] = {0.7f, 0.6f, 0.2f, 1.0f};
01099     static GLfloat shininess[1] = {100.0f};
01100     static GLfloat r[16] = {0};
01101     static GLfloat s[16] = {0};
01102 
01103 
01104     glMatrixMode(GL_MODELVIEW);
01105 
01106     glPushMatrix();
01107 
01108     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, amb_dif);
01109     glMaterialfv(GL_FRONT, GL_SPECULAR, amb_dif);
01110     glMaterialfv(GL_FRONT, GL_SHININESS, shininess);
01111 
01112     glTranslatef(scale*centroid->elts[0], scale*centroid->elts[1], 
01113             scale*centroid->elts[2]);
01114 
01115     const float* elts = *(R->elts);
01116     r[0] = elts[0];  r[4] = elts[1];  r[8]  = elts[2];
01117     r[1] = elts[3];  r[5] = elts[4];  r[9]  = elts[5];
01118     r[2] = elts[6];  r[6] = elts[7];  r[10] = elts[8];
01119     r[15] = 1;
01120     glMultMatrixf(r);
01121 
01122     s[0]  = scale*0.5f*width;
01123     s[5]  = scale*0.5f*width;
01124     s[10] = scale*0.5f*length;
01125     s[15] = 1.0f;
01126     glMultMatrixf(s);
01127 
01128     GLint slices = static_cast<GLint>(2.0f*width*scale);
01129     if (slices < 6)
01130         slices = 6;
01131     GLint stacks = static_cast<GLint>(length*scale);
01132     if (stacks < 3)
01133         stacks = 3;
01134     gluSphere(quad, 1, slices, stacks);
01135 
01136     glPopMatrix();
01137 }
01138 #endif
01139 
01140 
01157 float Spore::get_intersection
01158 (
01159     jwsc::Vector_f**      isect_out, 
01160     uint32_t              n,
01161     const jwsc::Vector_f* p1_in, 
01162     const jwsc::Vector_f* p2_in
01163 )
01164 throw (Arg_error)
01165 {
01166     if (n != 1 && n != 2)
01167     {
01168         throw Arg_error("Intersection number is not 1 or 2");
01169     }
01170 
01171     if (p1_in->num_elts != 3 || p2_in->num_elts != 3)
01172     {
01173         throw Arg_error("Line end-points are not in R^3");
01174     }
01175 
01176     // Transform a copy of the vectors to bring them into spore coords.
01177     Vector_f* p1 = 0;
01178     Vector_f* p2 = 0;
01179     Matrix_f* M  = 0;
01180     subtract_vectors_f(&p1, p1_in, centroid);
01181     subtract_vectors_f(&p2, p2_in, centroid);
01182     transpose_matrix_f(&M, R);
01183     multiply_matrix_and_vector_f(&p1, M, p1);
01184     multiply_matrix_and_vector_f(&p2, M, p2);
01185     free_matrix_f(M);
01186 
01187     float x1 = p1->elts[0];
01188     float y1 = p1->elts[1];
01189     float z1 = p1->elts[2];
01190 
01191     free_vector_f(p1);
01192 
01193     float x2 = p2->elts[0];
01194     float y2 = p2->elts[1];
01195     float z2 = p2->elts[2];
01196 
01197     free_vector_f(p2);
01198 
01199     float i = x2 - x1;
01200     float j = y2 - y1;
01201     float k = z2 - z1;
01202 
01203     float A = (2.0f / width)*(2.0f / width);
01204     float B = A;
01205     float C = (2.0f / length)*(2.0f / length);
01206 
01207     float a = A*i*i + B*j*j + C*k*k;
01208     float b = 2*A*x1*i + 2*B*y1*j + 2*C*z1*k;
01209     float c = A*x1*x1 + B*y1*y1 + C*z1*z1 - 1;
01210 
01211     float discriminant = b*b - 4*a*c;
01212     float t;
01213 
01214     if (discriminant < 0.0f)
01215     {
01216         // no real roots
01217         return -1;
01218     }
01219     else if (discriminant > 1.0e-6f)
01220     {
01221         // two real roots
01222         float t1 = (-b + sqrt(discriminant)) / (2*a);
01223         float t2 = (-b - sqrt(discriminant)) / (2*a);
01224 
01225         if ((n == 1 && t1 < t2) || (n == 2 && t1 > t2))
01226         {
01227             t = t1;
01228         }
01229         else
01230         {
01231             t = t2;
01232         }
01233     }
01234     else
01235     {
01236         // one real root
01237         t = (-b + sqrt(discriminant)) / (2*a);
01238     }
01239 
01240     // Handle precision problems.
01241     if (t < 0)
01242         t = 0;
01243     else if (t > 1.0f)
01244         t = 1.0f;
01245 
01246     create_vector_f(isect_out, 3);
01247     Vector_f* isect = *isect_out;
01248 
01249     isect->elts[0] = x1 + i*t;
01250     isect->elts[1] = y1 + j*t;
01251     isect->elts[2] = z1 + k*t;
01252 
01253     // Transform the intersection point to put it back in world coords.
01254     multiply_matrix_and_vector_f(&isect, R, isect);
01255     add_vectors_f(&isect, isect, centroid);
01256 
01257     return t;
01258 }
01259 
01260 
01262 void Spore::update_log_prob()
01263 {
01264     Apical_structure::update_log_prob();
01265 
01266     const DD_spore_set* dd_spores = density->get_dd_spores();
01267 
01268     if (dd_spores)
01269     {
01270         log_prob += dd_spores->get_similar_spore(this)->get_log_prob();
01271 
01272 #if defined ALTERNARIA_HAVE_ISINF && defined ALTERNARIA_HAVE_ISNAN
01273         assert(!std::isinf(log_prob) && !std::isnan(log_prob));
01274 #endif
01275     }
01276 }
01277 
01278 /* -------------------------------------------------------------------------- */
01279 
01280 
01281 
01282 
01283 
01284 
01285 
01286 /* ---------------------------  Printed_spore  ------------------------------ */
01287 
01293 Printed_spore::Printed_spore(const Spore_density* density)
01294 {
01295     id = 0;
01296     centroid_x = 0;
01297     centroid_y = 0;
01298     centroid_z = 0;
01299     length = 0;
01300     width = 0;
01301     base_theta = 0;
01302     base_psi = 0;
01303     theta = 0;
01304     psi = 0;
01305     opacity = 0;
01306     parent = 0;
01307     apical = 0;
01308     this->density = density;
01309 }
01310 
01311 
01320 Printed_spore::Printed_spore(std::istream& in, const Spore_density* density) 
01321     throw (IO_error, Arg_error)
01322 {
01323     this->density = density;
01324     read(in);
01325 }
01326 
01327 
01358 void Printed_spore::read(std::istream& in) throw (IO_error, Arg_error)
01359 {
01360     const char* member_value;
01361 
01362     if (!(member_value = Spore::get_member_value("Structure", in)))
01363     {
01364         throw Arg_error("Missing structure type");
01365     }
01366 
01367     if (strncmp(member_value, Spore::type_str(), strlen(Spore::type_str())) != 0)
01368     {
01369         ostringstream ost;
01370         ost << "Tried to read a '" << member_value << "' as a '"
01371             << Spore::type_str() << "'";
01372         throw Arg_error(ost.str());
01373     }
01374 
01375     read_id(in);
01376     read_level(in);
01377     read_centroid(in);
01378     read_length(in);
01379     read_width(in);
01380     read_base_theta(in);
01381     read_base_psi(in);
01382     read_theta(in);
01383     read_psi(in);
01384     read_opacity(in);
01385     read_parent(in);
01386     read_apical(in);
01387     read_laterals(in);
01388     read_log_prob(in);
01389 }
01390 
01391 
01403 Spore* Printed_spore::convert(Structure* parent) const throw (Arg_error)
01404 {
01405     if (parent)
01406     {
01407         return new Spore(parent, length, width, base_theta, base_psi, theta, 
01408                 psi, opacity, density);
01409     }
01410 
01411     return new Spore(centroid_x, centroid_y, centroid_z, length, width,
01412             base_theta, base_psi, theta, psi, opacity, level, density);
01413 }
01414 
01415 /* -------------------------------------------------------------------------- */