Alternaria
fit cylinders and ellipsoids to fungus
|
00001 /* 00002 * This work is licensed under a Creative Commons 00003 * Attribution-Noncommercial-Share Alike 3.0 United States License. 00004 * 00005 * http://creativecommons.org/licenses/by-nc-sa/3.0/us/ 00006 * 00007 * You are free: 00008 * 00009 * to Share - to copy, distribute, display, and perform the work 00010 * to Remix - to make derivative works 00011 * 00012 * Under the following conditions: 00013 * 00014 * Attribution. You must attribute the work in the manner specified by the 00015 * author or licensor (but not in any way that suggests that they endorse you 00016 * or your use of the work). 00017 * 00018 * Noncommercial. You may not use this work for commercial purposes. 00019 * 00020 * Share Alike. If you alter, transform, or build upon this work, you may 00021 * distribute the resulting work only under the same or similar license to 00022 * this one. 00023 * 00024 * For any reuse or distribution, you must make clear to others the license 00025 * terms of this work. The best way to do this is by including this header. 00026 * 00027 * Any of the above conditions can be waived if you get permission from the 00028 * copyright holder. 00029 * 00030 * Apart from the remix rights granted under this license, nothing in this 00031 * license impairs or restricts the author's moral rights. 00032 */ 00033 00034 00047 #include <config.h> 00048 00049 #include <cassert> 00050 #include <cmath> 00051 #include <cstring> 00052 #include <iostream> 00053 #include <sstream> 00054 #include <list> 00055 #include <vector> 00056 00057 #include <inttypes.h> 00058 00059 #if defined ALTERNARIA_HAVE_OPENGL_FRAMEWORK 00060 #include <OpenGL/gl.h> 00061 #include <OpenGL/glu.h> 00062 #elif defined ALTERNARIA_HAVE_OPENGL 00063 #include <GL/gl.h> 00064 #include <GL/glu.h> 00065 #endif 00066 00067 #include <jwsc/base/limits.h> 00068 #include <jwsc/math/constants.h> 00069 #include <jwsc/prob/pdf.h> 00070 #include <jwsc/vector/vector.h> 00071 #include <jwsc/vector/vector_math.h> 00072 #include <jwsc/matrix/matrix.h> 00073 #include <jwsc/matrix/matrix_math.h> 00074 #include <jwsc/matblock/matblock.h> 00075 00076 #include <jwsc++/base/exception.h> 00077 00078 #include "density.h" 00079 #include "printable.h" 00080 #include "structure.h" 00081 #include "spore.h" 00082 #include "hypha.h" 00083 00084 00085 #define CENTROID_X_MIN 0 00086 #define CENTROID_X_MAX 0 00087 00088 #define CENTROID_Y_MIN 0 00089 #define CENTROID_Y_MAX 0 00090 00091 #define CENTROID_Z_MIN 0 00092 #define CENTROID_Z_MAX 0 00093 00094 #define APICAL_LENGTH_MU 15.0f 00095 #define APICAL_LENGTH_SIGMA 1.0f 00096 #define APICAL_LENGTH_MIN 10.f 00097 #define APICAL_LENGTH_MAX 100.0f 00098 00099 #define LATERAL_LENGTH_MU 15.0f 00100 #define LATERAL_LENGTH_SIGMA 1.0f 00101 #define LATERAL_LENGTH_MIN 10.f 00102 #define LATERAL_LENGTH_MAX 100.0f 00103 00104 #define APICAL_WIDTH_MU 6.0f 00105 #define APICAL_WIDTH_SIGMA 0.3f 00106 #define APICAL_WIDTH_MIN 1.0f 00107 #define APICAL_WIDTH_MAX 20.0f 00108 00109 #define APICAL_DWIDTH_SIGMA 0.05f 00110 #define APICAL_DWIDTH_MIN -2.0f 00111 #define APICAL_DWIDTH_MAX 2.0f 00112 00113 #define LATERAL_WIDTH_MU 6.0f 00114 #define LATERAL_WIDTH_SIGMA 0.3f 00115 #define LATERAL_WIDTH_MIN 1.0f 00116 #define LATERAL_WIDTH_MAX 20.0f 00117 00118 #define APICAL_THETA_MU 0 00119 #define APICAL_THETA_SIGMA 0.2f 00120 #define APICAL_THETA_MIN 0 00121 #define APICAL_THETA_MAX JWSC_PI 00122 00123 #define LATERAL_THETA_MU JWSC_PI_4 00124 #define LATERAL_THETA_SIGMA 0.2f 00125 #define LATERAL_THETA_MIN 0 00126 #define LATERAL_THETA_MAX JWSC_PI 00127 00128 #define PSI_MIN -JWSC_PI 00129 #define PSI_MAX JWSC_PI 00130 00131 #define OPACITY_MU 0.9f 00132 #define OPACITY_SIGMA 0.2f 00133 #define OPACITY_MIN 0.1f 00134 #define OPACITY_MAX 1.0f 00135 00136 #define LAT_DIST_MU 0.5f 00137 #define LAT_DIST_SIGMA 0.1f 00138 #define LAT_DIST_MIN 0 00139 #define LAT_DIST_MAX 1.0f 00140 00141 00142 using std::istream; 00143 using std::ostringstream; 00144 using std::strncmp; 00145 using std::strlen; 00146 using std::list; 00147 using std::vector; 00148 using namespace jwsc; 00149 using jwscxx::base::Arg_error; 00150 using jwscxx::base::IO_error; 00151 00152 00153 /* ----------------------- Apical_hypha_density --------------------------- */ 00154 00161 Apical_hypha_density::Apical_hypha_density() throw (Arg_error) 00162 { 00163 float mu, sigma; 00164 float min, max; 00165 00166 min = CENTROID_X_MIN; 00167 max = CENTROID_X_MAX; 00168 set_centroid_x(min, max); 00169 00170 min = CENTROID_Y_MIN; 00171 max = CENTROID_Y_MAX; 00172 set_centroid_y(min, max); 00173 00174 min = CENTROID_Z_MIN; 00175 max = CENTROID_Z_MAX; 00176 set_centroid_z(min, max); 00177 00178 mu = APICAL_LENGTH_MU; 00179 sigma = APICAL_LENGTH_SIGMA; 00180 min = APICAL_LENGTH_MIN; 00181 max = APICAL_LENGTH_MAX; 00182 set_length(mu, sigma, min, max); 00183 00184 mu = APICAL_WIDTH_MU; 00185 sigma = APICAL_WIDTH_SIGMA; 00186 min = APICAL_WIDTH_MIN; 00187 max = APICAL_WIDTH_MAX; 00188 set_width(mu, sigma, min, max); 00189 00190 sigma = APICAL_DWIDTH_SIGMA; 00191 min = APICAL_DWIDTH_MIN; 00192 max = APICAL_DWIDTH_MAX; 00193 set_dwidth(sigma, min, max); 00194 00195 mu = APICAL_THETA_MU; 00196 sigma = APICAL_THETA_SIGMA; 00197 min = APICAL_THETA_MIN; 00198 max = APICAL_THETA_MAX; 00199 set_theta(mu, sigma, min, max); 00200 00201 min = PSI_MIN; 00202 max = PSI_MAX; 00203 set_psi(min, max); 00204 00205 mu = OPACITY_MU; 00206 sigma = OPACITY_SIGMA; 00207 min = OPACITY_MIN; 00208 max = OPACITY_MAX; 00209 set_opacity(mu, sigma, min, max); 00210 } 00211 00212 00214 Apical_hypha_density* Apical_hypha_density::clone() const 00215 { 00216 float mu, sigma; 00217 float min, max; 00218 00219 Apical_hypha_density* h = new Apical_hypha_density(); 00220 00221 min = centroid_x.get_min(); 00222 max = centroid_x.get_max(); 00223 h->set_centroid_x(min, max); 00224 00225 min = centroid_y.get_min(); 00226 max = centroid_y.get_max(); 00227 h->set_centroid_y(min, max); 00228 00229 min = centroid_z.get_min(); 00230 max = centroid_z.get_max(); 00231 h->set_centroid_z(min, max); 00232 00233 mu = length.get_mu(); 00234 sigma = length.get_sigma(); 00235 min = length.get_min(); 00236 max = length.get_max(); 00237 h->set_length(mu, sigma, min, max); 00238 00239 mu = width.get_mu(); 00240 sigma = width.get_sigma(); 00241 min = width.get_min(); 00242 max = width.get_max(); 00243 h->set_width(mu, sigma, min, max); 00244 00245 sigma = dwidth.get_sigma(); 00246 min = dwidth.get_min(); 00247 max = dwidth.get_max(); 00248 h->set_dwidth(sigma, min, max); 00249 00250 mu = theta.get_mu(); 00251 sigma = theta.get_sigma(); 00252 min = theta.get_min(); 00253 max = theta.get_max(); 00254 h->set_theta(mu, sigma, min, max); 00255 00256 min = psi.get_min(); 00257 max = psi.get_max(); 00258 h->set_psi(min, max); 00259 00260 mu = opacity.get_mu(); 00261 sigma = opacity.get_sigma(); 00262 min = opacity.get_min(); 00263 max = opacity.get_max(); 00264 h->set_opacity(mu, sigma, min, max); 00265 00266 return h; 00267 } 00268 00269 00280 void Apical_hypha_density::set_dwidth 00281 ( 00282 float sigma, 00283 float min, 00284 float max 00285 ) 00286 throw (Arg_error) 00287 { 00288 dwidth.set(0, sigma, min, max); 00289 } 00290 00291 00299 Apical_hypha* Apical_hypha_density::sample 00300 ( 00301 float base_theta, 00302 float base_psi, 00303 size_t level 00304 ) 00305 const 00306 { 00307 return new Apical_hypha(sample_centroid_x(), sample_centroid_y(), 00308 sample_centroid_z(), sample_length(), sample_width(), 00309 base_theta, base_psi, sample_theta(), sample_psi(), 00310 sample_opacity(), level, this); 00311 } 00312 00313 00327 Apical_hypha* Apical_hypha_density::sample 00328 ( 00329 float centroid_x, 00330 float centroid_y, 00331 float centroid_z, 00332 float base_theta, 00333 float base_psi, 00334 size_t level 00335 ) 00336 const throw (Arg_error) 00337 { 00338 return new Apical_hypha(centroid_x, centroid_y, centroid_z, sample_length(), 00339 sample_width(), base_theta, base_psi, sample_theta(), sample_psi(), 00340 sample_opacity(), level, this); 00341 } 00342 00343 00354 Apical_hypha* Apical_hypha_density::sample 00355 ( 00356 Structure* parent, 00357 float base_theta, 00358 float base_psi 00359 ) 00360 const throw (Arg_error) 00361 { 00362 if (dynamic_cast<Apical_hypha*>(parent) || 00363 dynamic_cast<Lateral_hypha*>(parent)) 00364 { 00365 return new Apical_hypha(parent, sample_length(), 00366 parent->get_width() + sample_dwidth(), base_theta, base_psi, 00367 sample_theta(), sample_psi(), sample_opacity(), this); 00368 } 00369 00370 return new Apical_hypha(parent, sample_length(), sample_width(), base_theta, 00371 base_psi, sample_theta(), sample_psi(), sample_opacity(), this); 00372 } 00373 00374 00376 float Apical_hypha_density::sample_dwidth() const 00377 { 00378 return (float)sample_gaussian_pdf_d(dwidth.get_mu(), dwidth.get_sigma(), 00379 dwidth.get_min(), dwidth.get_max()); 00380 } 00381 00382 /* -------------------------------------------------------------------------- */ 00383 00384 00385 00386 00387 00388 00389 /* ---------------------- Lateral_hypha_density --------------------------- */ 00390 00397 Lateral_hypha_density::Lateral_hypha_density() throw (Arg_error) 00398 { 00399 float mu, sigma; 00400 float min, max; 00401 00402 min = CENTROID_X_MIN; 00403 max = CENTROID_X_MAX; 00404 set_centroid_x(min, max); 00405 00406 min = CENTROID_Y_MIN; 00407 max = CENTROID_Y_MAX; 00408 set_centroid_y(min, max); 00409 00410 min = CENTROID_Z_MIN; 00411 max = CENTROID_Z_MAX; 00412 set_centroid_z(min, max); 00413 00414 mu = LATERAL_LENGTH_MU; 00415 sigma = LATERAL_LENGTH_SIGMA; 00416 min = LATERAL_LENGTH_MIN; 00417 max = LATERAL_LENGTH_MAX; 00418 set_length(mu, sigma, min, max); 00419 00420 mu = LATERAL_WIDTH_MU; 00421 sigma = LATERAL_WIDTH_SIGMA; 00422 min = LATERAL_WIDTH_MIN; 00423 max = LATERAL_WIDTH_MAX; 00424 set_width(mu, sigma, min, max); 00425 00426 mu = LATERAL_THETA_MU; 00427 sigma = LATERAL_THETA_SIGMA; 00428 min = LATERAL_THETA_MIN; 00429 max = LATERAL_THETA_MAX; 00430 set_theta(mu, sigma, min, max); 00431 00432 min = PSI_MIN; 00433 max = PSI_MAX; 00434 set_psi(min, max); 00435 00436 mu = OPACITY_MU; 00437 sigma = OPACITY_SIGMA; 00438 min = OPACITY_MIN; 00439 max = OPACITY_MAX; 00440 set_opacity(mu, sigma, min, max); 00441 00442 mu = LAT_DIST_MU; 00443 sigma = LAT_DIST_SIGMA; 00444 min = LAT_DIST_MIN; 00445 max = LAT_DIST_MAX; 00446 set_lat_dist(mu, sigma, min, max); 00447 } 00448 00449 00451 Lateral_hypha_density* Lateral_hypha_density::clone() const 00452 { 00453 float mu, sigma; 00454 float min, max; 00455 00456 Lateral_hypha_density* h = new Lateral_hypha_density(); 00457 00458 min = centroid_x.get_min(); 00459 max = centroid_x.get_max(); 00460 h->set_centroid_x(min, max); 00461 00462 min = centroid_y.get_min(); 00463 max = centroid_y.get_max(); 00464 h->set_centroid_y(min, max); 00465 00466 min = centroid_z.get_min(); 00467 max = centroid_z.get_max(); 00468 h->set_centroid_z(min, max); 00469 00470 mu = length.get_mu(); 00471 sigma = length.get_sigma(); 00472 min = length.get_min(); 00473 max = length.get_max(); 00474 h->set_length(mu, sigma, min, max); 00475 00476 mu = width.get_mu(); 00477 sigma = width.get_sigma(); 00478 min = width.get_min(); 00479 max = width.get_max(); 00480 h->set_width(mu, sigma, min, max); 00481 00482 mu = theta.get_mu(); 00483 sigma = theta.get_sigma(); 00484 min = theta.get_min(); 00485 max = theta.get_max(); 00486 h->set_theta(mu, sigma, min, max); 00487 00488 min = psi.get_min(); 00489 max = psi.get_max(); 00490 h->set_psi(min, max); 00491 00492 mu = opacity.get_mu(); 00493 sigma = opacity.get_sigma(); 00494 min = opacity.get_min(); 00495 max = opacity.get_max(); 00496 h->set_opacity(mu, sigma, min, max); 00497 00498 mu = lat_dist.get_mu(); 00499 sigma = lat_dist.get_sigma(); 00500 min = lat_dist.get_min(); 00501 max = lat_dist.get_max(); 00502 h->set_lat_dist(mu, sigma, min, max); 00503 00504 return h; 00505 } 00506 00507 00515 Lateral_hypha* Lateral_hypha_density::sample 00516 ( 00517 float base_theta, 00518 float base_psi, 00519 size_t level 00520 ) 00521 const 00522 { 00523 return new Lateral_hypha(sample_centroid_x(), sample_centroid_y(), 00524 sample_centroid_z(), sample_lat_dist(), sample_length(), 00525 sample_width(), base_theta, base_psi, sample_theta(), sample_psi(), 00526 sample_opacity(), level, this); 00527 } 00528 00529 00543 Lateral_hypha* Lateral_hypha_density::sample 00544 ( 00545 float centroid_x, 00546 float centroid_y, 00547 float centroid_z, 00548 float base_theta, 00549 float base_psi, 00550 size_t level 00551 ) 00552 const throw (Arg_error) 00553 { 00554 return new Lateral_hypha(centroid_x, centroid_y, centroid_z, 00555 sample_lat_dist(), sample_length(), sample_width(), base_theta, 00556 base_psi, sample_theta(), sample_psi(), sample_opacity(), level, 00557 this); 00558 } 00559 00560 00571 Lateral_hypha* Lateral_hypha_density::sample 00572 ( 00573 Structure* parent, 00574 float base_theta, 00575 float base_psi 00576 ) 00577 const throw (Arg_error) 00578 { 00579 return new Lateral_hypha(parent, sample_lat_dist(), sample_length(), 00580 sample_width(), base_theta, base_psi, sample_theta(), sample_psi(), 00581 sample_opacity(), this); 00582 } 00583 00584 /* -------------------------------------------------------------------------- */ 00585 00586 00587 00588 00589 00590 00591 00592 /* ---------------------------- Apical_hypha ------------------------------ */ 00593 00611 Apical_hypha::Apical_hypha 00612 ( 00613 float centroid_x, 00614 float centroid_y, 00615 float centroid_z, 00616 float length, 00617 float width, 00618 float base_theta, 00619 float base_psi, 00620 float theta, 00621 float psi, 00622 float opacity, 00623 size_t level, 00624 const class Apical_hypha_density* density 00625 ) 00626 throw (Arg_error) 00627 : Apical_structure(centroid_x, centroid_y, centroid_z, length, width, 00628 base_theta, base_psi, theta, psi, opacity, level, density) 00629 { 00630 this->density = density; 00631 00632 update_ancestry_log_prob(); 00633 } 00634 00635 00651 Apical_hypha::Apical_hypha 00652 ( 00653 Structure* parent, 00654 float length, 00655 float width, 00656 float base_theta, 00657 float base_psi, 00658 float theta, 00659 float psi, 00660 float opacity, 00661 const class Apical_hypha_density* density 00662 ) 00663 throw (Arg_error, Apical_error) 00664 : Apical_structure(parent, length, width, base_theta, base_psi, theta, psi, 00665 opacity, density) 00666 { 00667 this->density = density; 00668 00669 update_ancestry_log_prob(); 00670 } 00671 00672 00674 Apical_hypha::Apical_hypha(const Apical_hypha& h) : Apical_structure(h) 00675 { 00676 density = h.density; 00677 } 00678 00679 00681 Apical_hypha::Apical_hypha 00682 ( 00683 const class Spore& s, 00684 float width, 00685 const Apical_hypha_density* density 00686 ) 00687 throw (Arg_error) : Apical_structure(s) 00688 { 00689 Structure::density = density; 00690 Apical_structure::density = density; 00691 this->density = density; 00692 00693 this->width = width; 00694 00695 try 00696 { 00697 check_width(); 00698 check_length(); 00699 check_theta(); 00700 check_psi(); 00701 check_opacity(); 00702 } 00703 catch (Arg_error e) 00704 { 00705 apical = 0; 00706 laterals.clear(); 00707 00708 throw e; 00709 } 00710 00711 update_log_prob(); 00712 } 00713 00714 00716 Apical_hypha* Apical_hypha::clone() const 00717 { 00718 return new Apical_hypha(*this); 00719 } 00720 00721 00727 Apical_hypha& Apical_hypha::operator= (const Apical_hypha& h) 00728 { 00729 Apical_structure::operator=(h); 00730 00731 density = h.density; 00732 00733 return *this; 00734 } 00735 00736 00747 Apical_hypha* Apical_hypha::split_into_apical 00748 ( 00749 const Apical_hypha* rvals_1, 00750 const Apical_hypha* rvals_2 00751 ) 00752 throw (Arg_error) 00753 { 00754 return (Apical_hypha*)Apical_structure::split_into_apical(rvals_1, rvals_2); 00755 } 00756 00757 00772 Apical_hypha* Apical_hypha::merge_with_apical 00773 ( 00774 const Apical_hypha* rvals 00775 ) 00776 throw (Arg_error) 00777 { 00778 if (!apical) 00779 { 00780 throw Arg_error("No apical to merge with"); 00781 } 00782 00783 if (!dynamic_cast<Apical_hypha*>(apical)) 00784 { 00785 throw Arg_error("Apical to merge with not a hypha"); 00786 } 00787 00788 return (Apical_hypha*)Apical_structure::merge_with_apical(rvals); 00789 } 00790 00791 00807 Apical_hypha* Apical_hypha::merge_with_apical 00808 ( 00809 class Spore** spore_out, 00810 const class Spore* rvals 00811 ) 00812 throw (Arg_error) 00813 { 00814 assert(*spore_out == 0); 00815 00816 if (!apical) 00817 { 00818 throw Arg_error("No apical to merge with"); 00819 } 00820 00821 if (!dynamic_cast<Apical_hypha*>(apical)) 00822 { 00823 throw Arg_error("Apical to merge with not a hypha"); 00824 } 00825 00826 Apical_hypha hypha(*rvals, width, density); 00827 00828 Apical_hypha* merged = (Apical_hypha*)Apical_structure::merge_with_apical( 00829 &hypha); 00830 00831 *spore_out = new Spore(*this, rvals->get_width(), rvals->get_density()); 00832 00833 try 00834 { 00835 this->replace(*spore_out); 00836 } 00837 catch (Arg_error e) 00838 { 00839 delete *spore_out; 00840 delete merged; 00841 throw e; 00842 } 00843 00844 return merged; 00845 } 00846 00847 00858 Lateral_hypha* Apical_hypha::split_into_lateral 00859 ( 00860 const Apical_hypha* rvals_1, 00861 const class Lateral_hypha* rvals_2 00862 ) 00863 throw (Arg_error) 00864 { 00865 return (Lateral_hypha*)Apical_structure::split_into_lateral(rvals_1, 00866 rvals_2); 00867 } 00868 00869 00886 Lateral_hypha* Apical_hypha::merge_with_lateral 00887 ( 00888 class Lateral_hypha* lateral, 00889 const Apical_hypha* rvals 00890 ) 00891 throw (Arg_error) 00892 { 00893 return (Lateral_hypha*)Apical_structure::merge_with_lateral(lateral,rvals); 00894 } 00895 00896 00902 void Apical_hypha::replace(class Spore* spore) throw (Arg_error) 00903 { 00904 Apical_structure::replace(spore); 00905 } 00906 00907 00949 bool Apical_hypha::draw_in_matblock_f 00950 ( 00951 jwsc::Matblock_f* M_blk, 00952 float x, 00953 float y, 00954 float z, 00955 float x_scale, 00956 float y_scale, 00957 float z_scale, 00958 bool fill 00959 ) 00960 const 00961 { 00962 uint32_t num_mats, num_rows, num_cols; 00963 uint32_t mat, row, col; 00964 00965 float height, radius; 00966 float min_scale; 00967 float phi; 00968 float phi_step; 00969 float h; 00970 float h_step; 00971 float r; 00972 float r_step; 00973 float x_0, y_0, z_0; 00974 00975 Vector_f* point = 0; 00976 00977 num_mats = M_blk->num_mats; 00978 num_rows = M_blk->num_rows; 00979 num_cols = M_blk->num_cols; 00980 00981 height = length; 00982 radius = 0.5*width; 00983 00984 create_vector_f(&point, 3); 00985 00986 if (x_scale < y_scale && x_scale < z_scale) 00987 min_scale = x_scale; 00988 else if (y_scale < z_scale) 00989 min_scale = y_scale; 00990 else 00991 min_scale = z_scale; 00992 00993 h_step = 0.5*min_scale; 00994 r_step = (fill) ? 0.5*min_scale : radius; 00995 phi_step = 0.5*min_scale / radius; 00996 00997 bool intersect = false; 00998 00999 // Iterate over the points on the hypha parametrically and paint each 01000 // point in the matrix block. 01001 for (r = radius; r > 0; r -= r_step) 01002 { 01003 for (phi = 0; phi < 2*JWSC_PI; phi += phi_step) 01004 { 01005 x_0 = r*std::cos(phi); 01006 y_0 = r*std::sin(phi); 01007 01008 for (h = 0; h <= height; h += h_step) 01009 { 01010 z_0 = h; 01011 01012 point->elts[0] = x_0; 01013 point->elts[1] = y_0; 01014 point->elts[2] = z_0; 01015 multiply_matrix_and_vector_f(&point, R, point); 01016 add_vectors_f(&point, point, begin_pt); 01017 01018 col = static_cast<uint32_t>(std::floor( 01019 (point->elts[0] - x) / x_scale + 0.5)); 01020 row = static_cast<uint32_t>(std::floor( 01021 (point->elts[1] - y) / y_scale + 0.5)); 01022 mat = static_cast<uint32_t>(std::floor( 01023 (point->elts[2] - z) / z_scale + 0.5)); 01024 01025 if (mat >= 0 && mat < num_mats && 01026 row >= 0 && row < num_rows && 01027 col >= 0 && col < num_cols) 01028 { 01029 uint32_t current_id = (uint32_t)floor( 01030 M_blk->elts[ mat ][ row ][ col ]); 01031 01032 if (current_id > 0 && current_id != id && 01033 !has_child_id(current_id)) 01034 { 01035 intersect = true; 01036 } 01037 01038 M_blk->elts[ mat ][ row ][ col ] = (float)id + opacity; 01039 } 01040 } 01041 } 01042 } 01043 01044 free_vector_f(point); 01045 01046 return intersect; 01047 } 01048 01049 01054 #if defined ALTERNARIA_HAVE_OPENGL_FRAMEWORK || defined ALTERNARIA_HAVE_OPENGL 01055 void Apical_hypha::draw_in_opengl(GLUquadric* quad, float scale) const 01056 { 01057 static GLfloat amb_dif[4] = {0.5f, 0.7f, 0.6f, 1.0f}; 01058 static GLfloat shininess[1] = {100.0f}; 01059 static GLfloat r[16] = {0}; 01060 static GLfloat s[16] = {0}; 01061 01062 glMatrixMode(GL_MODELVIEW); 01063 01064 glPushMatrix(); 01065 01066 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, amb_dif); 01067 glMaterialfv(GL_FRONT, GL_SPECULAR, amb_dif); 01068 glMaterialfv(GL_FRONT, GL_SHININESS, shininess); 01069 01070 glTranslatef(scale*begin_pt->elts[0], scale*begin_pt->elts[1], 01071 scale*begin_pt->elts[2]); 01072 01073 const float* elts = *(R->elts); 01074 r[0] = elts[0]; r[4] = elts[1]; r[8] = elts[2]; 01075 r[1] = elts[3]; r[5] = elts[4]; r[9] = elts[5]; 01076 r[2] = elts[6]; r[6] = elts[7]; r[10] = elts[8]; 01077 r[15] = 1.0f; 01078 glMultMatrixf(r); 01079 01080 s[0] = scale*0.5f*width; 01081 s[5] = scale*0.5f*width; 01082 s[10] = scale*length; 01083 s[15] = 1.0f; 01084 glMultMatrixf(s); 01085 01086 GLint slices = static_cast<GLint>(2.0f*width*scale); 01087 if (slices < 6) 01088 slices = 6; 01089 GLint stacks = static_cast<GLint>(length*scale); 01090 if (stacks < 1) 01091 stacks = 1; 01092 gluCylinder(quad, 1, 1, 1, slices, stacks); 01093 01094 glPopMatrix(); 01095 } 01096 #endif 01097 01098 01115 float Apical_hypha::get_intersection 01116 ( 01117 jwsc::Vector_f** isect_out, 01118 uint32_t n, 01119 const jwsc::Vector_f* p1_in, 01120 const jwsc::Vector_f* p2_in 01121 ) 01122 throw (Arg_error) 01123 { 01124 if (n != 1 && n != 2) 01125 { 01126 throw Arg_error("Intersection number is not 1 or 2"); 01127 } 01128 01129 if (p1_in->num_elts != 3 || p2_in->num_elts != 3) 01130 { 01131 throw Arg_error("Line end-points are not in R^3"); 01132 } 01133 01134 // Transform a copy of the vectors to bring them into hypha coords. 01135 Vector_f* p1 = 0; 01136 Vector_f* p2 = 0; 01137 Matrix_f* M = 0; 01138 subtract_vectors_f(&p1, p1_in, centroid); 01139 subtract_vectors_f(&p2, p2_in, centroid); 01140 transpose_matrix_f(&M, R); 01141 multiply_matrix_and_vector_f(&p1, M, p1); 01142 multiply_matrix_and_vector_f(&p2, M, p2); 01143 free_matrix_f(M); 01144 01145 float x1 = p1->elts[0]; 01146 float y1 = p1->elts[1]; 01147 float z1 = p1->elts[2]; 01148 01149 free_vector_f(p1); 01150 01151 float x2 = p2->elts[0]; 01152 float y2 = p2->elts[1]; 01153 float z2 = p2->elts[2]; 01154 01155 free_vector_f(p2); 01156 01157 float i = x2 - x1; 01158 float j = y2 - y1; 01159 float k = z2 - z1; 01160 01161 float r = 0.5f*width; 01162 01163 float a = i*i + j*j; 01164 float b = 2*x1*i + 2*y1*j; 01165 float c = x1*x1 + y1*y1 - r*r; 01166 01167 float discriminant = b*b - 4*a*c; 01168 float t; 01169 01170 if (discriminant < 0.0f) 01171 { 01172 // no real roots 01173 return -1; 01174 } 01175 else if (discriminant > 1.0e-6f) 01176 { 01177 // two real roots 01178 float t1 = (-b + sqrt(discriminant)) / (2*a); 01179 float t2 = (-b - sqrt(discriminant)) / (2*a); 01180 01181 if ((n == 1 && t1 < t2) || (n == 2 && t1 > t2)) 01182 { 01183 t = t1; 01184 } 01185 else 01186 { 01187 t = t2; 01188 } 01189 } 01190 else 01191 { 01192 // one real root 01193 t = (-b + sqrt(discriminant)) / (2*a); 01194 } 01195 01196 // Handle precision problems. 01197 if (t < 0) 01198 t = 0; 01199 else if (t > 1.0f) 01200 t = 1.0f; 01201 01202 float x = x1 + i*t; 01203 float y = y1 + j*t; 01204 float z = z1 + k*t; 01205 01206 if (fabs(z) > 0.5f*length) 01207 { 01208 return -1; 01209 } 01210 01211 create_vector_f(isect_out, 3); 01212 Vector_f* isect = *isect_out; 01213 01214 isect->elts[0] = x; 01215 isect->elts[1] = y; 01216 isect->elts[2] = z; 01217 01218 // Transform the intersection point to put it back in world coords. 01219 multiply_matrix_and_vector_f(&isect, R, isect); 01220 add_vectors_f(&isect, isect, centroid); 01221 01222 return t; 01223 } 01224 01225 01227 void Apical_hypha::update_log_prob() 01228 { 01229 Apical_structure::update_log_prob(); 01230 01231 if (parent && (dynamic_cast<Apical_hypha*>(parent) || 01232 dynamic_cast<Lateral_hypha*>(parent))) 01233 { 01234 float mu, sigma; 01235 float min, max; 01236 double delta; 01237 double p_1, p_2; 01238 01239 /* Take out the width log prob. */ 01240 mu = density->get_width().get_mu(); 01241 sigma = density->get_width().get_sigma(); 01242 min = density->get_width().get_min(); 01243 max = density->get_width().get_max(); 01244 delta = (max - min) / 1000; 01245 p_1 = integrate_gaussian_pdf_d(mu, sigma, width, width+delta); 01246 p_2 = integrate_gaussian_pdf_d(mu, sigma, min, max); 01247 log_prob -= log((p_1 < JWSC_MIN_LOG_ARG) ? JWSC_MIN_LOG_ARG : p_1); 01248 log_prob += log((p_2 < JWSC_MIN_LOG_ARG) ? JWSC_MIN_LOG_ARG : p_2); 01249 01250 float w = width - parent->get_width(); 01251 01252 /* Put in the differential width log prob. */ 01253 mu = density->get_dwidth().get_mu(); 01254 sigma = density->get_dwidth().get_sigma(); 01255 min = density->get_dwidth().get_min(); 01256 max = density->get_dwidth().get_max(); 01257 delta = (max - min) / 1000; 01258 p_1 = integrate_gaussian_pdf_d(mu, sigma, w, w+delta); 01259 p_2 = integrate_gaussian_pdf_d(mu, sigma, min, max); 01260 log_prob += log((p_1 < JWSC_MIN_LOG_ARG) ? JWSC_MIN_LOG_ARG : p_1); 01261 log_prob -= log((p_2 < JWSC_MIN_LOG_ARG) ? JWSC_MIN_LOG_ARG : p_2); 01262 01263 #if defined ALTERNARIA_HAVE_ISINF && defined ALTERNARIA_HAVE_ISNAN 01264 assert(!std::isinf(log_prob) && !std::isnan(log_prob)); 01265 #endif 01266 } 01267 } 01268 01269 /* -------------------------------------------------------------------------- */ 01270 01271 01272 01273 01274 01275 01276 01277 /* ----------------------- Printed_apical_hypha --------------------------- */ 01278 01284 Printed_apical_hypha::Printed_apical_hypha(const Apical_hypha_density* density) 01285 { 01286 id = 0; 01287 centroid_x = 0; 01288 centroid_y = 0; 01289 centroid_z = 0; 01290 length = 0; 01291 width = 0; 01292 base_theta = 0; 01293 base_psi = 0; 01294 theta = 0; 01295 psi = 0; 01296 opacity = 0; 01297 level = 0; 01298 parent = 0; 01299 apical = 0; 01300 this->density = density; 01301 } 01302 01303 01312 Printed_apical_hypha::Printed_apical_hypha 01313 ( 01314 std::istream& in, 01315 const Apical_hypha_density* density 01316 ) 01317 throw (IO_error, Arg_error) 01318 { 01319 this->density = density; 01320 read(in); 01321 } 01322 01323 01354 void Printed_apical_hypha::read(std::istream& in) throw (IO_error, Arg_error) 01355 { 01356 const char* member_value; 01357 01358 if (!(member_value = Apical_hypha::get_member_value("Structure", in))) 01359 { 01360 throw Arg_error("Missing structure type"); 01361 } 01362 01363 if (strncmp(member_value, Apical_hypha::type_str(), 01364 strlen(Apical_hypha::type_str())) != 0) 01365 { 01366 ostringstream ost; 01367 ost << "Tried to read a '" << member_value << "' as a '" 01368 << Apical_hypha::type_str() << "'"; 01369 throw Arg_error(ost.str()); 01370 } 01371 01372 read_id(in); 01373 read_level(in); 01374 read_centroid(in); 01375 read_length(in); 01376 read_width(in); 01377 read_base_theta(in); 01378 read_base_psi(in); 01379 read_theta(in); 01380 read_psi(in); 01381 read_opacity(in); 01382 read_parent(in); 01383 read_apical(in); 01384 read_laterals(in); 01385 read_log_prob(in); 01386 } 01387 01388 01400 Apical_hypha* Printed_apical_hypha::convert(Structure* parent) const 01401 throw (Arg_error) 01402 { 01403 if (parent) 01404 { 01405 return new Apical_hypha(parent, length, width, base_theta, base_psi, 01406 theta, psi, opacity, density); 01407 } 01408 01409 return new Apical_hypha(centroid_x, centroid_y, centroid_z, length, width, 01410 base_theta, base_psi, theta, psi, opacity, level, density); 01411 } 01412 01413 /* -------------------------------------------------------------------------- */ 01414 01415 01416 01417 01418 01419 01420 01421 /* --------------------------- Lateral_hypha ------------------------------ */ 01422 01441 Lateral_hypha::Lateral_hypha 01442 ( 01443 float centroid_x, 01444 float centroid_y, 01445 float centroid_z, 01446 float lat_dist, 01447 float length, 01448 float width, 01449 float base_theta, 01450 float base_psi, 01451 float theta, 01452 float psi, 01453 float opacity, 01454 size_t level, 01455 const class Lateral_hypha_density* density 01456 ) 01457 throw (Arg_error) 01458 : Lateral_structure(centroid_x, centroid_y, centroid_z, lat_dist, length, 01459 width, base_theta, base_psi, theta, psi, opacity, level, density) 01460 { 01461 this->density = density; 01462 01463 update_ancestry_log_prob(); 01464 } 01465 01466 01483 Lateral_hypha::Lateral_hypha 01484 ( 01485 Structure* parent, 01486 float lat_dist, 01487 float length, 01488 float width, 01489 float base_theta, 01490 float base_psi, 01491 float theta, 01492 float psi, 01493 float opacity, 01494 const class Lateral_hypha_density* density 01495 ) 01496 throw (Arg_error, Apical_error) 01497 : Lateral_structure(parent, lat_dist, length, width, base_theta, base_psi, 01498 theta, psi, opacity, density) 01499 { 01500 this->density = density; 01501 01502 update_ancestry_log_prob(); 01503 } 01504 01505 01507 Lateral_hypha::Lateral_hypha(const Lateral_hypha& h) : Lateral_structure(h) 01508 { 01509 density = h.density; 01510 } 01511 01512 01514 Lateral_hypha* Lateral_hypha::clone() const 01515 { 01516 return new Lateral_hypha(*this); 01517 } 01518 01519 01525 Lateral_hypha& Lateral_hypha::operator= (const Lateral_hypha& h) 01526 { 01527 Lateral_structure::operator=(h); 01528 01529 density = h.density; 01530 01531 return *this; 01532 } 01533 01534 01576 bool Lateral_hypha::draw_in_matblock_f 01577 ( 01578 jwsc::Matblock_f* M_blk, 01579 float x, 01580 float y, 01581 float z, 01582 float x_scale, 01583 float y_scale, 01584 float z_scale, 01585 bool fill 01586 ) 01587 const 01588 { 01589 uint32_t num_mats, num_rows, num_cols; 01590 uint32_t mat, row, col; 01591 01592 float height, radius; 01593 float min_scale; 01594 float phi; 01595 float phi_step; 01596 float h; 01597 float h_step; 01598 float r; 01599 float r_step; 01600 float x_0, y_0, z_0; 01601 01602 Vector_f* point = 0; 01603 01604 num_mats = M_blk->num_mats; 01605 num_rows = M_blk->num_rows; 01606 num_cols = M_blk->num_cols; 01607 01608 height = length; 01609 radius = 0.5*width; 01610 01611 create_vector_f(&point, 3); 01612 01613 if (x_scale < y_scale && x_scale < z_scale) 01614 min_scale = x_scale; 01615 else if (y_scale < z_scale) 01616 min_scale = y_scale; 01617 else 01618 min_scale = z_scale; 01619 01620 h_step = 0.5*min_scale; 01621 r_step = (fill) ? 0.5*min_scale : radius; 01622 phi_step = 0.5*min_scale / radius; 01623 01624 bool intersect = false; 01625 01626 // Iterate over the points on the hypha parametrically and paint each 01627 // point in the matrix block. 01628 for (r = radius; r > 0; r -= r_step) 01629 { 01630 for (phi = 0; phi < 2*JWSC_PI; phi += phi_step) 01631 { 01632 x_0 = r*std::cos(phi); 01633 y_0 = r*std::sin(phi); 01634 01635 for (h = 0; h <= height; h += h_step) 01636 { 01637 z_0 = h; 01638 01639 point->elts[0] = x_0; 01640 point->elts[1] = y_0; 01641 point->elts[2] = z_0; 01642 multiply_matrix_and_vector_f(&point, R, point); 01643 add_vectors_f(&point, point, begin_pt); 01644 01645 col = static_cast<uint32_t>(std::floor( 01646 (point->elts[0] - x) / x_scale + 0.5)); 01647 row = static_cast<uint32_t>(std::floor( 01648 (point->elts[1] - y) / y_scale + 0.5)); 01649 mat = static_cast<uint32_t>(std::floor( 01650 (point->elts[2] - z) / z_scale + 0.5)); 01651 01652 01653 if (mat >= 0 && mat < num_mats && 01654 row >= 0 && row < num_rows && 01655 col >= 0 && col < num_cols) 01656 { 01657 uint32_t current_id = (uint32_t)floor( 01658 M_blk->elts[ mat ][ row ][ col ]); 01659 01660 if (current_id > 0 && current_id != id && 01661 !has_child_id(current_id)) 01662 { 01663 intersect = true; 01664 } 01665 01666 M_blk->elts[ mat ][ row ][ col ] = id + opacity; 01667 } 01668 } 01669 } 01670 } 01671 01672 free_vector_f(point); 01673 01674 return intersect; 01675 } 01676 01677 01682 #if defined ALTERNARIA_HAVE_OPENGL_FRAMEWORK || defined ALTERNARIA_HAVE_OPENGL 01683 void Lateral_hypha::draw_in_opengl(GLUquadric* quad, float scale) const 01684 { 01685 static GLfloat amb_dif[4] = {0.7f, 0.8f, 0.9f, 1.0f}; 01686 static GLfloat shininess[1] = {100.0f}; 01687 static GLfloat r[16] = {0}; 01688 static GLfloat s[16] = {0}; 01689 01690 glMatrixMode(GL_MODELVIEW); 01691 01692 glPushMatrix(); 01693 01694 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, amb_dif); 01695 glMaterialfv(GL_FRONT, GL_SPECULAR, amb_dif); 01696 glMaterialfv(GL_FRONT, GL_SHININESS, shininess); 01697 01698 glTranslatef(scale*begin_pt->elts[0], scale*begin_pt->elts[1], 01699 scale*begin_pt->elts[2]); 01700 01701 const float* elts = *(R->elts); 01702 r[0] = elts[0]; r[4] = elts[1]; r[8] = elts[2]; 01703 r[1] = elts[3]; r[5] = elts[4]; r[9] = elts[5]; 01704 r[2] = elts[6]; r[6] = elts[7]; r[10] = elts[8]; 01705 r[15] = 1.0f; 01706 glMultMatrixf(r); 01707 01708 s[0] = scale*0.5f*width; 01709 s[5] = scale*0.5f*width; 01710 s[10] = scale*length; 01711 s[15] = 1.0f; 01712 glMultMatrixf(s); 01713 01714 GLint slices = static_cast<GLint>(2.0f*width*scale); 01715 if (slices < 6) 01716 slices = 6; 01717 GLint stacks = static_cast<GLint>(length*scale); 01718 if (stacks < 1) 01719 stacks = 1; 01720 gluCylinder(quad, 1, 1, 1, slices, stacks); 01721 01722 glPopMatrix(); 01723 } 01724 #endif 01725 01726 01744 float Lateral_hypha::get_intersection 01745 ( 01746 jwsc::Vector_f** isect_out, 01747 uint32_t n, 01748 const jwsc::Vector_f* p1_in, 01749 const jwsc::Vector_f* p2_in 01750 ) 01751 throw (Arg_error) 01752 { 01753 if (n != 1 && n != 2) 01754 { 01755 throw Arg_error("Intersection number is not 1 or 2"); 01756 } 01757 01758 if (p1_in->num_elts != 3 || p2_in->num_elts != 3) 01759 { 01760 throw Arg_error("Line end-points are not in R^3"); 01761 } 01762 01763 // Transform a copy of the vectors to bring them into hypha coords. 01764 Vector_f* p1 = 0; 01765 Vector_f* p2 = 0; 01766 Matrix_f* M = 0; 01767 subtract_vectors_f(&p1, p1_in, centroid); 01768 subtract_vectors_f(&p2, p2_in, centroid); 01769 transpose_matrix_f(&M, R); 01770 multiply_matrix_and_vector_f(&p1, M, p1); 01771 multiply_matrix_and_vector_f(&p2, M, p2); 01772 free_matrix_f(M); 01773 01774 float x1 = p1->elts[0]; 01775 float y1 = p1->elts[1]; 01776 float z1 = p1->elts[2]; 01777 01778 free_vector_f(p1); 01779 01780 float x2 = p2->elts[0]; 01781 float y2 = p2->elts[1]; 01782 float z2 = p2->elts[2]; 01783 01784 free_vector_f(p2); 01785 01786 float i = x2 - x1; 01787 float j = y2 - y1; 01788 float k = z2 - z1; 01789 01790 float r = 0.5f*width; 01791 01792 float a = i*i + j*j; 01793 float b = 2*x1*i + 2*y1*j; 01794 float c = x1*x1 + y1*y1 - r*r; 01795 01796 float discriminant = b*b - 4*a*c; 01797 float t; 01798 01799 if (discriminant < 0.0f) 01800 { 01801 // no real roots 01802 return -1; 01803 } 01804 else if (discriminant > 1.0e-6f) 01805 { 01806 // two real roots 01807 float t1 = (-b + sqrt(discriminant)) / (2*a); 01808 float t2 = (-b - sqrt(discriminant)) / (2*a); 01809 01810 if ((n == 1 && t1 < t2) || (n == 2 && t1 > t2)) 01811 { 01812 t = t1; 01813 } 01814 else 01815 { 01816 t = t2; 01817 } 01818 } 01819 else 01820 { 01821 // one real root 01822 t = (-b + sqrt(discriminant)) / (2*a); 01823 } 01824 01825 // Handle precision problems. 01826 if (t < 0) 01827 t = 0; 01828 else if (t > 1.0f) 01829 t = 1.0f; 01830 01831 float x = x1 + i*t; 01832 float y = y1 + j*t; 01833 float z = z1 + k*t; 01834 01835 if (fabs(z) > 0.5f*length) 01836 { 01837 return -1; 01838 } 01839 01840 create_vector_f(isect_out, 3); 01841 Vector_f* isect = *isect_out; 01842 01843 isect->elts[0] = x; 01844 isect->elts[1] = y; 01845 isect->elts[2] = z; 01846 01847 // Transform the intersection point to put it back in world coords. 01848 multiply_matrix_and_vector_f(&isect, R, isect); 01849 add_vectors_f(&isect, isect, centroid); 01850 01851 return t; 01852 } 01853 01854 /* -------------------------------------------------------------------------- */ 01855 01856 01857 01858 01859 01860 01861 01862 01863 /* ----------------------- Printed_lateral_hypha -------------------------- */ 01864 01871 Printed_lateral_hypha::Printed_lateral_hypha 01872 ( 01873 const Lateral_hypha_density* level_1_density, 01874 const Lateral_hypha_density* level_n_density 01875 ) 01876 { 01877 id = 0; 01878 centroid_x = 0; 01879 centroid_y = 0; 01880 centroid_z = 0; 01881 length = 0; 01882 width = 0; 01883 base_theta = 0; 01884 base_psi = 0; 01885 theta = 0; 01886 psi = 0; 01887 opacity = 0; 01888 level = 0; 01889 parent = 0; 01890 apical = 0; 01891 this->level_1_density = level_1_density; 01892 this->level_n_density = level_n_density; 01893 } 01894 01895 01904 Printed_lateral_hypha::Printed_lateral_hypha 01905 ( 01906 std::istream& in, 01907 const Lateral_hypha_density* level_1_density, 01908 const Lateral_hypha_density* level_n_density 01909 ) 01910 throw (IO_error, Arg_error) 01911 { 01912 this->level_1_density = level_1_density; 01913 this->level_n_density = level_n_density; 01914 read(in); 01915 } 01916 01917 01949 void Printed_lateral_hypha::read(std::istream& in) throw (IO_error, Arg_error) 01950 { 01951 const char* member_value; 01952 01953 if (!(member_value = Lateral_hypha::get_member_value("Structure", in))) 01954 { 01955 throw Arg_error("Missing structure type"); 01956 } 01957 01958 if (strncmp(member_value, Lateral_hypha::type_str(), 01959 strlen(Lateral_hypha::type_str())) != 0) 01960 { 01961 ostringstream ost; 01962 ost << "Tried to read a '" << member_value << "' as a '" 01963 << Lateral_hypha::type_str() << "'"; 01964 throw Arg_error(ost.str()); 01965 } 01966 01967 read_id(in); 01968 read_level(in); 01969 read_centroid(in); 01970 read_length(in); 01971 read_width(in); 01972 read_base_theta(in); 01973 read_base_psi(in); 01974 read_theta(in); 01975 read_psi(in); 01976 read_opacity(in); 01977 read_parent(in); 01978 read_apical(in); 01979 read_laterals(in); 01980 read_log_prob(in); 01981 read_lat_dist(in); 01982 } 01983 01984 01996 Lateral_hypha* Printed_lateral_hypha::convert(Structure* parent) const 01997 throw (Arg_error) 01998 { 01999 const Lateral_hypha_density* density = (level == 1) ? level_1_density 02000 : level_n_density; 02001 02002 if (parent) 02003 { 02004 return new Lateral_hypha(parent, lat_dist, length, width, base_theta, 02005 base_psi, theta, psi, opacity, density); 02006 } 02007 02008 return new Lateral_hypha(centroid_x, centroid_y, centroid_z, lat_dist, 02009 length, width, base_theta, base_psi, theta, psi, opacity, level, 02010 density); 02011 } 02012 02013 /* -------------------------------------------------------------------------- */