Alternaria
fit cylinders and ellipsoids to fungus
|
00001 /* 00002 * This work is licensed under a Creative Commons 00003 * Attribution-Noncommercial-Share Alike 3.0 United States License. 00004 * 00005 * http://creativecommons.org/licenses/by-nc-sa/3.0/us/ 00006 * 00007 * You are free: 00008 * 00009 * to Share - to copy, distribute, display, and perform the work 00010 * to Remix - to make derivative works 00011 * 00012 * Under the following conditions: 00013 * 00014 * Attribution. You must attribute the work in the manner specified by the 00015 * author or licensor (but not in any way that suggests that they endorse you 00016 * or your use of the work). 00017 * 00018 * Noncommercial. You may not use this work for commercial purposes. 00019 * 00020 * Share Alike. If you alter, transform, or build upon this work, you may 00021 * distribute the resulting work only under the same or similar license to 00022 * this one. 00023 * 00024 * For any reuse or distribution, you must make clear to others the license 00025 * terms of this work. The best way to do this is by including this header. 00026 * 00027 * Any of the above conditions can be waived if you get permission from the 00028 * copyright holder. 00029 * 00030 * Apart from the remix rights granted under this license, nothing in this 00031 * license impairs or restricts the author's moral rights. 00032 */ 00033 00034 00046 #include <config.h> 00047 00048 #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 /* -------------------------------------------------------------------------- */