Alternaria
fit cylinders and ellipsoids to fungus
alternaria_gen.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 
00047 #include <config.h>
00048 
00049 #include <cstdlib>
00050 #include <cstdio>
00051 #include <cstring>
00052 #include <iostream>
00053 #include <sstream>
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 #if defined ALTERNARIA_HAVE_GLUT_FRAMEWORK
00067 #include <GLUT/glut.h>
00068 #elif defined ALTERNARIA_HAVE_GLUT
00069 #include <GL/glut.h>
00070 #endif
00071 
00072 #include <jwsc/prob/pdf.h>
00073 #include <jwsc/math/constants.h>
00074 #include <jwsc/vector/vector.h>
00075 #include <jwsc/vector/vector_math.h>
00076 #include <jwsc/matrix/matrix.h>
00077 #include <jwsc/matrix/matrix_math.h>
00078 #include <jwsc/image/image.h>
00079 #include <jwsc/image/image_io.h>
00080 
00081 #include <jwsc++/base/option.h>
00082 #include <jwsc++/base/exception.h>
00083 #include <jwsc++/graphics/camera.h>
00084 
00085 #include "imaging_model.h"
00086 #include "psf_model.h"
00087 #include "structure.h"
00088 #include "spore.h"
00089 #include "hypha.h"
00090 #include "alternaria_model.h"
00091 
00092 
00093 /* Anaglyph glasses filter types. */
00094 #define REDBLUE  1
00095 #define REDGREEN 2
00096 #define REDCYAN  3
00097 #define BLUERED  4
00098 #define GREENRED 5
00099 #define CYANRED  6
00100 
00101 /* Program defaults. */
00102 #define  VIEW_WIDTH      800
00103 #define  VIEW_HEIGHT     800
00104 #define  APERTURE        60.0f
00105 #define  CLIP_NEAR       10.0f
00106 #define  CLIP_FAR        3000.0f
00107 #define  GLASSES_TYPE    REDCYAN
00108 #define  CAPTURE_FMT     "capture-%04u.tiff"
00109 #define  OBJECT_SCALE    1.0
00110 #define  SEED            2537984
00111 #define  IMG_IN_FNAME    0
00112 #define  IMG_OUT_FNAME   "imaging.model"
00113 #define  PSF_IN_FNAME    0
00114 #define  PSF_OUT_FNAME   "psf.model"
00115 #define  ALT_IN_FNAME    0
00116 #define  ALT_OUT_FNAME   "alternaria.model"
00117 #define  ALT_SCENE_FMT   0
00118 #define  PSF_H_FMT       0
00119 #define  NUM_SCENE_COLS  128
00120 #define  NUM_SCENE_ROWS  128
00121 #define  NUM_SCENE_IMGS  128
00122 #define  CENTROID_MIN    -5000.0f
00123 #define  CENTROID_MAX    5000.0f
00124 #define  NUM_STRUCTS     300
00125 #define  BASE_LEVEL      0
00126 
00127 
00128 using std::cout;
00129 using std::cerr;
00130 using std::ostringstream;
00131 using std::sscanf;
00132 using std::vector;
00133 using namespace jwsc;
00134 using jwscxx::base::Options;
00135 using jwscxx::base::Exception;
00136 using jwscxx::base::Arg_error;
00137 using jwscxx::base::IO_error;
00138 using jwscxx::graphics::Stereo_camera_f;
00139 
00140 
00142 Options* opts = 0;
00143 
00145 uint32_t view_width = VIEW_WIDTH;
00146 
00148 uint32_t view_height = VIEW_HEIGHT;
00149 
00151 float aperture = APERTURE;
00152 
00154 float clip_near = CLIP_NEAR;
00155 
00157 float clip_far = CLIP_FAR;
00158 
00160 int glasses_type = GLASSES_TYPE;
00161 
00163 const char* capture_fmt = CAPTURE_FMT;
00164 
00166 float object_scale = OBJECT_SCALE;
00167 
00169 uint32_t seed = SEED;
00170 
00172 const char* img_in_fname = IMG_IN_FNAME;
00173 
00175 const char* img_out_fname = IMG_OUT_FNAME;
00176 
00178 const char* psf_in_fname = PSF_IN_FNAME;
00179 
00181 const char* psf_out_fname = PSF_OUT_FNAME;
00182 
00184 const char* alt_in_fname = ALT_IN_FNAME;
00185 
00187 const char* alt_out_fname = ALT_OUT_FNAME;
00188 
00193 const char* alt_scene_fmt = ALT_SCENE_FMT;
00194 
00196 const char* psf_h_fmt = PSF_H_FMT;
00197 
00199 uint32_t num_structs = NUM_STRUCTS;
00200 
00202 uint32_t base_level = BASE_LEVEL;
00203 
00205 Imaging_window* img_window = 0;
00206 
00208 Imaging_scale* img_scale = 0;
00209 
00211 Imaging_model* imaging = 0;
00212 
00214 PSF_padding* padding = 0;
00215 
00217 PSF_model* psf = 0;
00218 
00220 Alternaria* alternaria = 0;
00221 
00223 Imaging_model_density* imaging_d = 0;
00224 
00226 PSF_model_density* psf_d = 0;
00227 
00229 Apical_hypha_density* apical_hypha_d = 0;
00230 
00232 Lateral_hypha_density* lateral_hypha_1_d = 0;
00233 
00235 Lateral_hypha_density* lateral_hypha_n_d = 0;
00236 
00238 Spore_density* spore_d = 0;
00239 
00241 Alternaria_density* alt_d = 0;
00242 
00244 bool interactive = 0;
00245 
00247 Stereo_camera_f* camera = 0;
00248 
00250 GLUquadric* quad_fill = 0;
00251 
00253 GLUquadric* quad_wire = 0;
00254 
00259 Structure* highlight = 0;
00260 
00266 struct Alternaria_gen_modes
00267 {
00269     bool translate_camera;
00270 
00272     bool rotate_camera;
00273 
00275     bool modify_structure;
00276 
00278     bool capture_view;
00279 
00284     bool anaglyph;
00285 
00287     bool render_focal_plane;
00288 
00290     bool render_world_axis;
00291 
00293     bool focal_prp;
00294 
00296     bool focal_vrp;
00297 }
00298 modes;
00299 
00301 void init_modes()
00302 {
00303     modes.translate_camera   = false;
00304     modes.rotate_camera      = true;
00305     modes.modify_structure   = false;
00306     modes.capture_view       = false;
00307     modes.anaglyph           = false;
00308     modes.render_focal_plane = false;
00309     modes.render_world_axis  = true;
00310     modes.focal_prp          = false;
00311     modes.focal_vrp          = true;
00312 }
00313 
00315 void init_camera() throw (Arg_error)
00316 {
00317     delete camera;
00318 
00319     camera = new Stereo_camera_f(0, 50, 300, 0, 50, 0, 0, 1, 0,
00320             aperture, clip_near, clip_far);
00321 }
00322 
00328 void clean_up()
00329 {
00330     delete img_window;
00331     delete img_scale;
00332     delete padding;
00333     delete alternaria;
00334     delete psf;
00335     delete imaging;
00336     delete imaging_d;
00337     delete psf_d;
00338     delete spore_d;
00339     delete apical_hypha_d;
00340     delete lateral_hypha_1_d;
00341     delete lateral_hypha_n_d;
00342     delete alt_d;
00343     delete camera;
00344     delete opts;
00345     gluDeleteQuadric(quad_fill);
00346     gluDeleteQuadric(quad_wire);
00347 }
00348 
00350 void reset()
00351 {
00352     object_scale = OBJECT_SCALE;
00353     aperture     = APERTURE;
00354     highlight    = 0;
00355     init_camera();
00356     init_modes();
00357 }
00358 
00360 void render_world_axis()
00361 {
00362     static GLfloat amb_dif[4] = {0, 0, 0, 1.0f};
00363 
00364     glMatrixMode(GL_MODELVIEW);
00365 
00366     glPushMatrix();
00367 
00368     float axis_length  = 100.0f;
00369     float arrow_radius = axis_length / 10.0f;
00370     float arrow_height = axis_length / 5.0f;
00371 
00372     /* X */
00373     amb_dif[0] = 0.9f;  amb_dif[1] = 1.0f;  amb_dif[2] = 0.3f;
00374     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, amb_dif);
00375     glPushMatrix();
00376       glRotatef(90, 0, 1.0f, 0);
00377       gluCylinder(quad_fill, 1, 1, axis_length - 0.5f*arrow_height, 8, 1);
00378     glPopMatrix();
00379     glPushMatrix();
00380       glTranslatef(axis_length - arrow_height, 0, 0);
00381       glRotatef(90, 0, 1.0f, 0);
00382       gluCylinder(quad_fill, arrow_radius, 0, arrow_height, 16, 8);
00383     glPopMatrix();
00384 
00385     /* Y */
00386     amb_dif[0] = 0.9f;  amb_dif[1] = 1.0f;  amb_dif[2] = 0.3f;
00387     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, amb_dif);
00388     glPushMatrix();
00389       glRotatef(-90, 1.0f, 0, 0);
00390       gluCylinder(quad_fill, 1, 1, axis_length - 0.5f*arrow_height, 8, 1);
00391     glPopMatrix();
00392     glPushMatrix();
00393       glTranslatef(0, axis_length - arrow_height, 0);
00394       glRotatef(-90, 1.0f, 0, 0);
00395       gluCylinder(quad_fill, arrow_radius, 0, arrow_height, 16, 8);
00396     glPopMatrix();
00397 
00398     /* Z */
00399     amb_dif[0] = 0.9f;  amb_dif[1] = 1.0f;  amb_dif[2] = 0.3f;
00400     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, amb_dif);
00401     gluCylinder(quad_fill, 1, 1, axis_length - 0.5f*arrow_height, 8, 1);
00402     glPushMatrix();
00403       glTranslatef(0, 0, axis_length - arrow_height);
00404       gluCylinder(quad_fill, arrow_radius, 0, arrow_height, 16, 8);
00405     glPopMatrix();
00406 
00407     glPopMatrix();
00408 }
00409 
00411 void render_focal_plane()
00412 {
00413     static GLfloat amb_dif[4] = {0.7f, 0.6f, 0.5f, 0.2f};
00414     GLboolean prev_blend;
00415     GLint     prev_blend_src;
00416     GLint     prev_blend_dst;
00417 
00418     if ((prev_blend = glIsEnabled(GL_BLEND)))
00419     {
00420         glGetIntegerv(GL_BLEND_SRC, &prev_blend_src);
00421         glGetIntegerv(GL_BLEND_DST, &prev_blend_dst);
00422     }
00423     else
00424     {
00425         glEnable(GL_BLEND);
00426     }
00427     glBlendFunc(GL_SRC_ALPHA, GL_SRC_ALPHA);
00428 
00429     glMatrixMode(GL_MODELVIEW);
00430 
00431     glPushMatrix();
00432     glLoadIdentity();
00433 
00434     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, amb_dif);
00435 
00436     float x = 200.0f;
00437     float y = 200.0f;
00438     float z = -camera->get_focal_length();
00439 
00440     glBegin(GL_POLYGON);
00441     glNormal3f( 0,  0, 1);
00442     glVertex3f( x,  y, z);
00443     glVertex3f(-x,  y, z);
00444     glVertex3f(-x, -y, z);
00445     glVertex3f( x, -y, z);
00446     glEnd();
00447 
00448     glPopMatrix();
00449 
00450     if (prev_blend)
00451     {
00452         glBlendFunc(prev_blend_src, prev_blend_dst);
00453     }
00454     else
00455     {
00456         glDisable(GL_BLEND);
00457     }
00458 }
00459 
00461 void render_scene()
00462 {
00463     glMatrixMode(GL_MODELVIEW);
00464 
00465     glPushMatrix();
00466 
00467     float x = object_scale*alternaria->get_root()->get_centroid()->elts[0];
00468     float y = object_scale*alternaria->get_root()->get_centroid()->elts[1];
00469     float z = object_scale*alternaria->get_root()->get_centroid()->elts[2];
00470     glTranslatef(-x, -y, -z);
00471 
00472     if (highlight)
00473     {
00474         glEnable(GL_LIGHT1);
00475         highlight->draw_in_opengl(quad_fill, object_scale);
00476         glDisable(GL_LIGHT1);
00477     }
00478 
00479     alternaria->get_root()->recursively_draw_in_opengl(quad_fill, object_scale);
00480 
00481     glPopMatrix();
00482 }
00483 
00485 void display_glut_anaglyph()
00486 {
00487     /* Set the buffer for reading and writing. Using double buffering. */
00488     glDrawBuffer(GL_BACK);
00489     glReadBuffer(GL_BACK);
00490 
00491     /* Clear things */
00492     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT);
00493 
00494     /* Left camera filter. */
00495     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
00496     switch (glasses_type) 
00497     {
00498         case REDBLUE:
00499         case REDGREEN:
00500         case REDCYAN:
00501             glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE);
00502             break;
00503         case BLUERED:
00504             glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE);
00505             break;
00506         case GREENRED:
00507             glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE);
00508             break;
00509         case CYANRED:
00510             glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE);
00511             break;
00512     } 
00513 
00514     /* Set the left camera projection. */
00515     camera->set_left_gl_projection();
00516 
00517     /* Set the camera model view. */
00518     camera->set_left_gl_modelview();
00519 
00520     /* Render the world axis. */
00521     if (modes.render_world_axis)
00522     {
00523         render_world_axis();
00524     }
00525 
00526     render_scene();
00527 
00528     /* Render the focal plane if in that mode. */
00529     if (modes.render_focal_plane)
00530     {
00531         render_focal_plane();
00532     }
00533 
00534     glFlush();
00535 
00536     glAccum(GL_LOAD, 0.5f);
00537     glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
00538 
00539     /* Right camera filter. */
00540     switch (glasses_type) 
00541     {
00542         case REDBLUE:
00543             glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE);
00544             break;
00545         case REDGREEN:
00546             glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE);
00547             break;
00548         case REDCYAN:
00549             glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE);
00550             break;
00551         case BLUERED:
00552         case GREENRED:
00553         case CYANRED:
00554             glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE);
00555             break;
00556     } 
00557 
00558     /* Set the right camera projection. */
00559     camera->set_right_gl_projection();
00560 
00561     /* Set the camera model view. */
00562     camera->set_right_gl_modelview();
00563 
00564     /* Render the world axis. */
00565     if (modes.render_world_axis)
00566     {
00567         render_world_axis();
00568     }
00569 
00570     render_scene();
00571 
00572     /* Render the focal plane if in that mode. */
00573     if (modes.render_focal_plane)
00574     {
00575         render_focal_plane();
00576     }
00577 
00578     glFlush();
00579 
00581     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
00582 
00583     glAccum(GL_ACCUM, 0.5f);
00584     glAccum(GL_RETURN, 2.0f);
00585 }
00586 
00590 void display_glut_regular()
00591 {
00592     /* Set the buffer for writing. Using double buffering. */
00593     glDrawBuffer(GL_BACK);
00594     glReadBuffer(GL_BACK);
00595 
00596     /* Clear things */
00597     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00598 
00599     /* Set the camera projection. */
00600     camera->set_gl_projection();
00601 
00602     /* Set the camera model view. */
00603     camera->set_gl_modelview();
00604 
00605     /* Render the world axis. */
00606     if (modes.render_world_axis)
00607     {
00608         render_world_axis();
00609     }
00610 
00611     render_scene();
00612 
00613     /* Render the focal plane if in that mode. */
00614     if (modes.render_focal_plane)
00615     {
00616         render_focal_plane();
00617     }
00618 
00619     glFlush();
00620 }
00621 
00623 void display_glut()
00624 {
00625     static uint32_t N = 1;
00626 
00627     if (modes.anaglyph)
00628     {
00629         display_glut_anaglyph();
00630     }
00631     else
00632     {
00633         display_glut_regular();
00634     }
00635 
00636     glutSwapBuffers();
00637 
00638     if (modes.capture_view)
00639     {
00640         Stereo_camera_f::capture_gl_view(capture_fmt, N++);
00641         modes.capture_view = 0;
00642     }
00643 }
00644 
00645 
00647 void reshape_glut(int w, int h)
00648 {
00649     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00650     glViewport(0, 0, (GLsizei)w, (GLsizei)h); 
00651     view_width = w;
00652     view_height = h;
00653 }
00654 
00656 void keyboard_glut(unsigned char key, int a, int b)
00657 {
00658     float translate_delta = 10;
00659     float rotate_delta    = 10*JWSC_DEG_TO_RAD;
00660     float focal_length;
00661     float theta;
00662 
00663     Vector_f* v_tmp = 0;
00664     Alternaria* alt;
00665 
00666     switch (key) {
00667         case 't':
00668             modes.translate_camera = true;
00669             modes.rotate_camera = false;
00670             modes.modify_structure = false;
00671             break;
00672         case 'r':
00673             modes.rotate_camera = true;
00674             modes.translate_camera = false;
00675             modes.modify_structure = false;
00676             break;
00677         case 'l':
00678             if (modes.translate_camera)
00679             {
00680                 const Vector_f* right = camera->get_u();
00681                 camera->translate(
00682                         translate_delta * right->elts[0],
00683                         translate_delta * right->elts[1],
00684                         translate_delta * right->elts[2]);
00685             }
00686             else if (modes.rotate_camera)
00687             {
00688                 camera->rotate(-rotate_delta, 0, 1, 0);
00689             }
00690             else if (modes.modify_structure && highlight)
00691             {
00692                 float width = highlight->get_width();
00693                 try 
00694                 {
00695                     highlight->set_width(width + 0.5);
00696                 }
00697                 catch (Arg_error e)
00698                 {
00699                     e.print_details();
00700                 }
00701             }
00702             glutPostRedisplay();
00703             break;
00704         case 'h':
00705             if (modes.translate_camera)
00706             {
00707                 const Vector_f* right = camera->get_u();
00708                 camera->translate(
00709                         -translate_delta * right->elts[0],
00710                         -translate_delta * right->elts[1],
00711                         -translate_delta * right->elts[2]);
00712             }
00713             else if (modes.rotate_camera)
00714             {
00715                 camera->rotate(rotate_delta, 0, 1, 0);
00716             }
00717             else if (modes.modify_structure && highlight)
00718             {
00719                 float width = highlight->get_width();
00720                 try 
00721                 {
00722                     highlight->set_width(width - 0.5);
00723                 }
00724                 catch (Arg_error e)
00725                 {
00726                     e.print_details();
00727                 }
00728             }
00729             glutPostRedisplay();
00730             break;
00731         case 'L':
00732             if (modes.translate_camera)
00733             {
00734                 const Vector_f* right = camera->get_u();
00735                 camera->translate(
00736                         translate_delta * right->elts[0],
00737                         translate_delta * right->elts[1],
00738                         translate_delta * right->elts[2]);
00739             }
00740             else if (modes.rotate_camera)
00741             {
00742                 copy_vector_f(&v_tmp, camera->get_prp());
00743                 multiply_vector_by_scalar_f(&v_tmp, v_tmp, -1);
00744                 camera->translate(v_tmp);
00745                 camera->rotate(rotate_delta, camera->get_v());
00746                 multiply_vector_by_scalar_f(&v_tmp, v_tmp, -1);
00747                 camera->translate(v_tmp);
00748             }
00749             else if (modes.modify_structure && highlight)
00750             {
00751                 float psi = highlight->get_psi() + 0.1f*JWSC_PI_2;
00752                 if (psi > spore_d->get_psi().get_max() 
00753                         && (psi - JWSC_2_PI) >= spore_d->get_psi().get_min())
00754                 {
00755                     psi -= JWSC_2_PI;
00756                 }
00757                 try 
00758                 {
00759                     highlight->set_psi(psi);
00760                 }
00761                 catch (Arg_error e)
00762                 {
00763                     e.print_details();
00764                 }
00765             }
00766             glutPostRedisplay();
00767             break;
00768         case 'H':
00769             if (modes.translate_camera)
00770             {
00771                 const Vector_f* right = camera->get_u();
00772                 camera->translate(
00773                         -translate_delta * right->elts[0],
00774                         -translate_delta * right->elts[1],
00775                         -translate_delta * right->elts[2]);
00776             }
00777             else if (modes.rotate_camera)
00778             {
00779                 copy_vector_f(&v_tmp, camera->get_prp());
00780                 multiply_vector_by_scalar_f(&v_tmp, v_tmp, -1);
00781                 camera->translate(v_tmp);
00782                 camera->rotate(-rotate_delta, camera->get_v());
00783                 multiply_vector_by_scalar_f(&v_tmp, v_tmp, -1);
00784                 camera->translate(v_tmp);
00785             }
00786             else if (modes.modify_structure && highlight)
00787             {
00788                 float psi = highlight->get_psi() - 0.1f*JWSC_PI_2;
00789                 if (psi < spore_d->get_psi().get_min() 
00790                         && (psi + JWSC_2_PI) <= spore_d->get_psi().get_max())
00791                 {
00792                     psi += JWSC_2_PI;
00793                 }
00794                 try 
00795                 {
00796                     highlight->set_psi(psi);
00797                 }
00798                 catch (Arg_error e)
00799                 {
00800                     e.print_details();
00801                 }
00802             }
00803             glutPostRedisplay();
00804             break;
00805         case 'k':
00806             if (modes.translate_camera)
00807             {
00808                 const Vector_f* up = camera->get_v();
00809                 camera->translate(
00810                         translate_delta * up->elts[0],
00811                         translate_delta * up->elts[1],
00812                         translate_delta * up->elts[2]);
00813             }
00814             else if (modes.rotate_camera)
00815             {
00816                 camera->rotate(rotate_delta, camera->get_u());
00817             }
00818             else if (modes.modify_structure && highlight)
00819             {
00820                 float length = highlight->get_length();
00821                 try 
00822                 {
00823                     highlight->set_length(length + 1);
00824                 }
00825                 catch (Arg_error e)
00826                 {
00827                     e.print_details();
00828                 }
00829             }
00830             glutPostRedisplay();
00831             break;
00832         case 'j':
00833             if (modes.translate_camera)
00834             {
00835                 const Vector_f* up = camera->get_v();
00836                 camera->translate(
00837                         -translate_delta * up->elts[0],
00838                         -translate_delta * up->elts[1],
00839                         -translate_delta * up->elts[2]);
00840             }
00841             else if (modes.rotate_camera)
00842             {
00843                 camera->rotate(-rotate_delta, camera->get_u());
00844             }
00845             else if (modes.modify_structure && highlight)
00846             {
00847                 float length = highlight->get_length();
00848                 try 
00849                 {
00850                     highlight->set_length(length - 1);
00851                 }
00852                 catch (Arg_error e)
00853                 {
00854                     e.print_details();
00855                 }
00856             }
00857             glutPostRedisplay();
00858             break;
00859         case 'K':
00860             if (modes.translate_camera)
00861             {
00862                 const Vector_f* view = camera->get_n();
00863                 camera->translate(
00864                         -translate_delta * view->elts[0],
00865                         -translate_delta * view->elts[1],
00866                         -translate_delta * view->elts[2]);
00867             }
00868             else if (modes.rotate_camera)
00869             {
00870                 copy_vector_f(&v_tmp, camera->get_prp());
00871                 multiply_vector_by_scalar_f(&v_tmp, v_tmp, -1);
00872                 camera->translate(v_tmp);
00873                 camera->rotate(-rotate_delta, camera->get_u());
00874                 multiply_vector_by_scalar_f(&v_tmp, v_tmp, -1);
00875                 camera->translate(v_tmp);
00876             }
00877             else if (modes.modify_structure && highlight)
00878             {
00879                 float theta = highlight->get_theta();
00880                 try 
00881                 {
00882                     highlight->set_theta(theta + 0.1f*JWSC_PI_2);
00883                 }
00884                 catch (Arg_error e)
00885                 {
00886                     e.print_details();
00887                 }
00888             }
00889             glutPostRedisplay();
00890             break;
00891         case 'J':
00892             if (modes.translate_camera)
00893             {
00894                 const Vector_f* view = camera->get_n();
00895                 camera->translate(
00896                         translate_delta * view->elts[0],
00897                         translate_delta * view->elts[1],
00898                         translate_delta * view->elts[2]);
00899             }
00900             else if (modes.rotate_camera)
00901             {
00902                 copy_vector_f(&v_tmp, camera->get_prp());
00903                 multiply_vector_by_scalar_f(&v_tmp, v_tmp, -1);
00904                 camera->translate(v_tmp);
00905                 camera->rotate(rotate_delta, camera->get_u());
00906                 multiply_vector_by_scalar_f(&v_tmp, v_tmp, -1);
00907                 camera->translate(v_tmp);
00908             }
00909             else if (modes.modify_structure && highlight)
00910             {
00911                 float theta = highlight->get_theta();
00912                 try 
00913                 {
00914                     highlight->set_theta(theta - 0.1f*JWSC_PI_2);
00915                 }
00916                 catch (Arg_error e)
00917                 {
00918                     e.print_details();
00919                 }
00920             }
00921             glutPostRedisplay();
00922             break;
00923         case 'v':
00924             if (modes.modify_structure && highlight 
00925                     && dynamic_cast<Apical_structure*>(highlight))
00926             {
00927                 Apical_structure* apical = (Apical_structure*)highlight;
00928                 const Vector_f* centroid = apical->get_centroid();
00929                 float x = centroid->elts[0] + 
00930                           sample_gaussian_pdf_d(0, 1, -10, 10);
00931                 float y = centroid->elts[1] +
00932                           sample_gaussian_pdf_d(0, 1, -10, 10);
00933                 float z = centroid->elts[2] +
00934                           sample_gaussian_pdf_d(0, 1, -10, 10);
00935                 try 
00936                 {
00937                     apical->set_position(x, y, z);
00938                 }
00939                 catch (Arg_error e)
00940                 {
00941                     e.print_details();
00942                 }
00943                 glutPostRedisplay();
00944             }
00945             break;
00946         case 'V':
00947             break;
00948         case 'b':
00949             if (modes.modify_structure && highlight 
00950                     && dynamic_cast<Lateral_structure*>(highlight))
00951             {
00952                 Lateral_structure* lat = (Lateral_structure*)highlight;
00953                 float lat_dist = lat->get_lat_dist();
00954                 try 
00955                 {
00956                     lat->set_lat_dist(lat_dist - 0.1);
00957                 }
00958                 catch (Arg_error e)
00959                 {
00960                     Structure* parent = 0;
00961                     float max = lat->get_density()->get_lat_dist().get_max();
00962 
00963                     if (dynamic_cast<Apical_structure*>(lat->get_parent()) &&
00964                             (parent = lat->get_parent()->get_parent()))
00965                     {
00966                         try
00967                         {
00968                             lat->set_parent(parent, max - 0.1);
00969                         }
00970                         catch (Arg_error e)
00971                         {
00972                             e.print_details();
00973                         }
00974                     }
00975                     else
00976                     {
00977                         e.print_details();
00978                     }
00979                 }
00980                 glutPostRedisplay();
00981             }
00982             break;
00983         case 'B':
00984             if (modes.modify_structure && highlight 
00985                     && dynamic_cast<Lateral_structure*>(highlight))
00986             {
00987                 Lateral_structure* lat = (Lateral_structure*)highlight;
00988                 float lat_dist = lat->get_lat_dist();
00989                 try 
00990                 {
00991                     lat->set_lat_dist(lat_dist + 0.1);
00992                 }
00993                 catch (Arg_error e)
00994                 {
00995                     Apical_structure* apical = 0;
00996                     float min = lat->get_density()->get_lat_dist().get_min();
00997 
00998                     if (lat->get_parent() && 
00999                             (apical = lat->get_parent()->get_apical()))
01000                     {
01001                         try
01002                         {
01003                             lat->set_parent(apical, min + 0.1);
01004                         }
01005                         catch (Arg_error e)
01006                         {
01007                             e.print_details();
01008                         }
01009                     }
01010                     else
01011                     {
01012                         e.print_details();
01013                     }
01014                 }
01015                 glutPostRedisplay();
01016             }
01017             break;
01018         case 'm':
01019             if (modes.modify_structure && highlight 
01020                     && dynamic_cast<Apical_hypha*>(highlight))
01021             {
01022                 Apical_hypha* rvals_1 = 0;
01023                 Apical_hypha* rvals_2 = 0;
01024 
01025                 try
01026                 {
01027                     float width_1 = highlight->get_width() + 
01028                         apical_hypha_d->sample_dwidth();
01029                     float width_2 = highlight->get_width() + 
01030                         apical_hypha_d->sample_dwidth();
01031                     rvals_1 = apical_hypha_d->sample();
01032                     rvals_1->set_width(width_1);
01033                     rvals_2 = apical_hypha_d->sample();
01034                     rvals_2->set_width(width_2);
01035                     alternaria->split_apical_hypha_into_apical(
01036                             (Apical_hypha*)highlight, rvals_1, rvals_2);
01037                     highlight = 0;
01038                     delete rvals_1;
01039                     delete rvals_2;
01040                 }
01041                 catch (Arg_error e)
01042                 {
01043                     delete rvals_1;
01044                     delete rvals_2;
01045                     e.print_details();
01046                 }
01047             }
01048             else if (modes.modify_structure && highlight 
01049                     && dynamic_cast<Spore*>(highlight))
01050             {
01051                 Spore* rvals_1 = spore_d->sample();
01052                 Spore* rvals_2 = spore_d->sample();
01053 
01054                 float width = 0.65f*highlight->get_width();
01055                 float sigma = spore_d->get_width().get_sigma();
01056                 float min   = -6.0f*sigma;
01057                 float max   = 6.0f*sigma;
01058 
01059                 try
01060                 {
01061                     width += sample_gaussian_pdf_d(0, sigma, min, max);
01062                     rvals_1->set_width(width);
01063                     width += sample_gaussian_pdf_d(0, sigma, min, max);
01064                     rvals_1->set_width(width);
01065                     alternaria->split_spore_into_spore(
01066                             (Spore*)highlight, rvals_1, rvals_2);
01067                     highlight = 0;
01068                     delete rvals_1;
01069                     delete rvals_2;
01070                 }
01071                 catch (Arg_error e)
01072                 {
01073                     delete rvals_1;
01074                     delete rvals_2;
01075                     e.print_details();
01076                 }
01077             }
01078             glutPostRedisplay();
01079             break;
01080         case 'M':
01081             if (modes.modify_structure && highlight 
01082                     && dynamic_cast<Apical_hypha*>(highlight))
01083             {
01084                 Apical_hypha* rvals = 0;
01085 
01086                 try
01087                 {
01088                     float width = highlight->get_width() + 
01089                         apical_hypha_d->sample_dwidth();
01090                     rvals = apical_hypha_d->sample();
01091                     rvals->set_width(width);
01092                     alternaria->merge_apical_hypha_with_apical(
01093                             (Apical_hypha*)highlight, rvals);
01094                     highlight = 0;
01095                     delete rvals;
01096                 }
01097                 catch (Arg_error e)
01098                 {
01099                     delete rvals;
01100                     e.print_details();
01101                 }
01102             }
01103             else if (modes.modify_structure && highlight 
01104                     && highlight->get_apical()
01105                     && dynamic_cast<Spore*>(highlight))
01106             {
01107                 Spore* rvals = spore_d->sample();
01108 
01109                 float width = 0.65f*highlight->get_width() + 
01110                               0.65f*highlight->get_apical()->get_width();
01111                 float sigma = spore_d->get_width().get_sigma();
01112                 float min   = -6.0f*sigma;
01113                 float max   = 6.0f*sigma;
01114 
01115                 try
01116                 {
01117                     width += sample_gaussian_pdf_d(0, sigma, min, max);
01118                     rvals->set_width(width);
01119                     alternaria->merge_spore_with_spore((Spore*)highlight,rvals);
01120                     highlight = 0;
01121                     delete rvals;
01122                 }
01123                 catch (Arg_error e)
01124                 {
01125                     delete rvals;
01126                     e.print_details();
01127                 }
01128             }
01129             glutPostRedisplay();
01130             break;
01131         case 'n':
01132             if (modes.modify_structure && highlight 
01133                     && dynamic_cast<Apical_hypha*>(highlight))
01134             {
01135                 Apical_hypha* rvals_1 = 0;
01136                 Lateral_hypha* rvals_2 = 0;
01137 
01138                 try
01139                 {
01140                     float width = highlight->get_width() + 
01141                         apical_hypha_d->sample_dwidth();
01142                     rvals_1 = apical_hypha_d->sample();
01143                     rvals_1->set_width(width);
01144                     if (highlight->get_level() == 0)
01145                     {
01146                         rvals_2 = lateral_hypha_1_d->sample();
01147                     }
01148                     else
01149                     {
01150                         rvals_2 = lateral_hypha_n_d->sample();
01151                     }
01152                     alternaria->split_apical_hypha_into_lateral(
01153                             (Apical_hypha*)highlight, rvals_1, rvals_2);
01154                     delete rvals_1;
01155                     delete rvals_2;
01156                 }
01157                 catch (Arg_error e)
01158                 {
01159                     delete rvals_1;
01160                     delete rvals_2;
01161                     e.print_details();
01162                 }
01163                 glutPostRedisplay();
01164             }
01165             break;
01166         case 'N':
01167             if (modes.modify_structure && highlight && highlight->get_parent()
01168                     && dynamic_cast<Apical_hypha*>(highlight->get_parent())
01169                     && dynamic_cast<Lateral_hypha*>(highlight))
01170             {
01171                 Apical_hypha* rvals = 0;
01172 
01173                 try
01174                 {
01175                     float width = highlight->get_width() + 
01176                         apical_hypha_d->sample_dwidth();
01177                     rvals = apical_hypha_d->sample();
01178                     rvals->set_width(width);
01179                     alternaria->merge_apical_hypha_with_lateral(
01180                             (Apical_hypha*)highlight->get_parent(), 
01181                             (Lateral_hypha*)highlight, rvals);
01182                     highlight = 0;
01183                     delete rvals;
01184                 }
01185                 catch (Arg_error e)
01186                 {
01187                     delete rvals;
01188                     e.print_details();
01189                 }
01190                 glutPostRedisplay();
01191             }
01192             break;
01193         case 'F':
01194             if (modes.focal_prp)
01195             {
01196                 focal_length = camera->get_focal_length() + 20;
01197                 camera->set_f_with_same_aperture_using_prp(focal_length);
01198             }
01199             else if (modes.focal_vrp)
01200             {
01201                 focal_length = camera->get_focal_length() + 20;
01202                 camera->set_f_with_same_aperture_using_vrp(focal_length);
01203             }
01204             glutPostRedisplay();
01205             break;
01206         case 'f':
01207             if (modes.focal_prp)
01208             {
01209                 focal_length = camera->get_focal_length();
01210                 if (focal_length >= 22)
01211                 {
01212                     focal_length -= 20;
01213                     camera->set_f_with_same_aperture_using_prp(focal_length);
01214                 }
01215             }
01216             else if (modes.focal_vrp)
01217             {
01218                 focal_length = camera->get_focal_length();
01219                 if (focal_length >= 22)
01220                 {
01221                     focal_length -= 20;
01222                     camera->set_f_with_same_aperture_using_vrp(focal_length);
01223                 }
01224             }
01225             glutPostRedisplay();
01226             break;
01227         case 'S':
01228             if (object_scale >= 2.99f)
01229             {
01230                 object_scale = 3.0f;
01231             }
01232             else
01233             {
01234                 object_scale += 0.01f;
01235             }
01236             glutPostRedisplay();
01237             break;
01238         case 's':
01239             if (object_scale > 0.01f)
01240             {
01241                 object_scale -= 0.01f;
01242             }
01243             glutPostRedisplay();
01244             break;
01245         case 'A':
01246             aperture += JWSC_PI_8;
01247             camera->set_aperture(aperture);
01248             glutPostRedisplay();
01249             break;
01250         case 'a':
01251             theta = aperture - JWSC_PI_8;
01252             if (theta >= 0)
01253             {
01254                 aperture = theta;
01255                 camera->set_aperture(theta);
01256             }
01257             glutPostRedisplay();
01258             break;
01259         case 'c':
01260             modes.capture_view = 1;
01261             glutPostRedisplay();
01262             break;
01263         case 'C':
01264             alt = alternaria->clone();
01265             delete alternaria;
01266             alternaria = alt;
01267             highlight = 0;
01268             glutPostRedisplay();
01269             break;
01270         case 'o':
01271             reset();
01272             glutPostRedisplay();
01273             break;
01274         case 'w':
01275             imaging->print(img_out_fname);
01276             psf->print(psf_out_fname);
01277             alternaria->print(alt_out_fname);
01278             break;
01279         case 'W':
01280             if (psf_h_fmt)
01281             {
01282                 psf->write_h(psf_h_fmt);
01283             }
01284             if (alt_scene_fmt)
01285             {
01286                 Alternaria_model* model = new Alternaria_model(*alternaria, 
01287                         psf, imaging);
01288                 model->write_scene(alt_scene_fmt, psf);
01289                 delete model;
01290             }
01291             break;
01292         case 'q':
01293             free_vector_f(v_tmp);
01294             clean_up();
01295             exit(EXIT_SUCCESS);
01296     }
01297 
01298     free_vector_f(v_tmp);
01299 }
01300 
01302 void mouse_glut(int button, int state, int x, int y)
01303 {
01304     Vector_f* near_pt  = 0;
01305     Vector_f* far_pt   = 0;
01306     Vector_f* isect_pt = 0;
01307 
01308     if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
01309     {
01310         float u = (float)x - (float)view_width / 2.0f;
01311         float v = (float)view_height / 2.0f - (float)y;
01312         camera->get_image_pt_on_near_clipping_plane(&near_pt, u, v);
01313         camera->get_image_pt_on_far_clipping_plane(&far_pt, u, v);
01314 
01315         // Undo the transformation of the view in render_scene().
01316         multiply_vector_by_scalar_f(&near_pt, near_pt, 1.0f/object_scale);
01317         multiply_vector_by_scalar_f(&far_pt, far_pt, 1.0f/object_scale);
01318 
01319         float x = alternaria->get_root()->get_centroid()->elts[0];
01320         float y = alternaria->get_root()->get_centroid()->elts[1];
01321         float z = alternaria->get_root()->get_centroid()->elts[2];
01322         Vector_f* V = 0;
01323         create_vector_f(&V, 3);
01324         V->elts[0] = x; V->elts[1] = y; V->elts[2] = z;
01325         add_vectors_f(&near_pt, near_pt, V);
01326         add_vectors_f(&far_pt, far_pt, V);
01327         free_vector_f(V);
01328 
01329         highlight = 0;
01330         float t_min = 1.0f;
01331 
01332         vector<Structure*>* structs = alternaria->get_root()->get_descendants();
01333 
01334         for (size_t i = 0; i < structs->size(); i++)
01335         {
01336             float t = structs->at(i)->get_intersection(&isect_pt, 1, near_pt, 
01337                     far_pt);
01338             if (t >= 0 && t <= t_min)
01339             {
01340                 t_min = t;
01341                 highlight = structs->at(i);
01342             }
01343         }
01344 
01345         delete structs;
01346 
01347         if (highlight)
01348         {
01349             highlight->print();
01350         }
01351 
01352         glutPostRedisplay();
01353     }
01354 
01355     free_vector_f(near_pt);
01356     free_vector_f(far_pt);
01357     free_vector_f(isect_pt);
01358 }
01359 
01361 void main_menu_glut(int id)
01362 {
01363     switch (id)
01364     {
01365         case 0:
01366             modes.capture_view = 1;
01367             glutPostRedisplay();
01368             break;
01369         case 1:
01370             reset();
01371             glutPostRedisplay();
01372             break;
01373         case 2:
01374             clean_up();
01375             exit(EXIT_SUCCESS);
01376     }
01377 }
01378 
01380 void option_menu_glut(int id)
01381 {
01382     switch (id)
01383     {
01384         case 0:
01385             modes.anaglyph = !modes.anaglyph;
01386             glutPostRedisplay();
01387             break;
01388         case 1:
01389             modes.render_focal_plane = !modes.render_focal_plane;
01390             glutPostRedisplay();
01391             break;
01392         case 2:
01393             modes.render_world_axis = !modes.render_world_axis;
01394             glutPostRedisplay();
01395             break;
01396     }
01397 }
01398 
01400 void navigation_menu_glut(int id)
01401 {
01402     switch (id)
01403     {
01404         case 0:
01405             modes.rotate_camera    = true;
01406             modes.translate_camera = false;
01407             modes.modify_structure = false;
01408             break;
01409         case 1:
01410             modes.rotate_camera    = false;
01411             modes.translate_camera = true;
01412             modes.modify_structure = false;
01413             break;
01414         case 2:
01415             modes.rotate_camera    = false;
01416             modes.translate_camera = false;
01417             modes.modify_structure = true;
01418             break;
01419     }
01420 }
01421 
01423 void focal_length_menu_glut(int id)
01424 {
01425     switch (id)
01426     {
01427         case 0:
01428             modes.focal_prp = true;
01429             modes.focal_vrp = false;
01430             break;
01431         case 1:
01432             modes.focal_prp = false;
01433             modes.focal_vrp = true;
01434             break;
01435     }
01436 }
01437 
01439 void init_glut(int argc, char** argv)
01440 {
01441     glutInit(&argc, argv);
01442     glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_ACCUM
01443                                     | GLUT_ALPHA);
01444     glutInitWindowSize(view_width, view_height);
01445     glutCreateWindow("Alternaria Structure Tester");
01446     glutDisplayFunc(display_glut); 
01447     glutReshapeFunc(reshape_glut);
01448     glutKeyboardFunc(keyboard_glut);
01449     glutMouseFunc(mouse_glut);
01450 
01451     int navigation = glutCreateMenu(navigation_menu_glut);
01452     glutAddMenuEntry("Rotate Camera", 0);
01453     glutAddMenuEntry("Translate Camera", 1);
01454     glutAddMenuEntry("Modify Structure", 2);
01455 
01456     int focal_length = glutCreateMenu(focal_length_menu_glut);
01457     glutAddMenuEntry("PRP", 0);
01458     glutAddMenuEntry("VRP", 1);
01459 
01460     int options = glutCreateMenu(option_menu_glut);
01461     glutAddMenuEntry("Anaglyph", 0);
01462     glutAddMenuEntry("Focal Plane", 1);
01463     glutAddMenuEntry("Axis", 2);
01464 
01465     glutCreateMenu(main_menu_glut);
01466     glutAddSubMenu("Navigation", navigation);
01467     glutAddSubMenu("Focal Length", focal_length);
01468     glutAddSubMenu("Options", options);
01469     glutAddMenuEntry("Capture", 1);
01470     glutAddMenuEntry("Reset", 2);
01471     glutAddMenuEntry("Quit", 3);
01472 
01473     glutAttachMenu(GLUT_RIGHT_BUTTON);
01474 }
01475 
01477 void init_gl() 
01478 {
01479     glEnable(GL_DEPTH_TEST);
01480     glEnable(GL_NORMALIZE);
01481     glEnable(GL_LIGHTING);
01482 
01483     static GLfloat base_amb[] = {0.0f, 0.0f, 0.0f, 0.0f};
01484     glLightModelfv(GL_LIGHT_MODEL_AMBIENT, base_amb);
01485 
01486     static GLfloat ambient0  [] = {0.2f, 0.2f, 0.2f, 1.0f};
01487     static GLfloat diffuse0  [] = {0.8f, 0.8f, 0.8f, 1.0f};
01488     static GLfloat specular0 [] = {0.9f, 0.9f, 0.9f, 1.0f};
01489     static GLfloat direction0[] = {500.0f, 500.0f, 2000.0f, 1.0f};
01490 
01491     glEnable(GL_LIGHT0);
01492     glLightfv(GL_LIGHT0, GL_AMBIENT, ambient0);
01493     glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse0);
01494     glLightfv(GL_LIGHT0, GL_SPECULAR, specular0);
01495     glLightfv(GL_LIGHT0, GL_POSITION, direction0);
01496 
01497     static GLfloat ambient1  [] = {0.1f, 0.1f, 0.1f, 1.0f};
01498     static GLfloat diffuse1  [] = {0.4f, 0.4f, 0.4f, 1.0f};
01499     static GLfloat specular1 [] = {0.5f, 0.5f, 0.5f, 1.0f};
01500     static GLfloat direction1[] = {500.0f, 500.0f, 2000.0f, 1.0f};
01501 
01502     glDisable(GL_LIGHT1);
01503     glLightfv(GL_LIGHT1, GL_AMBIENT, ambient1);
01504     glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse1);
01505     glLightfv(GL_LIGHT1, GL_SPECULAR, specular1);
01506     glLightfv(GL_LIGHT1, GL_POSITION, direction1);
01507 
01508     if (!quad_fill)
01509     {
01510         quad_fill = gluNewQuadric();
01511         gluQuadricDrawStyle(quad_fill, GLU_FILL);
01512     }
01513 
01514     if (!quad_wire)
01515     {
01516         quad_wire = gluNewQuadric();
01517         gluQuadricDrawStyle(quad_wire, GLU_LINE);
01518     }
01519 
01520     glLineWidth(1.0);
01521     glPointSize(1.0);
01522     glClearColor(0.0, 0.0, 0.0, 0.0);
01523     glClearAccum(0.0, 0.0, 0.0, 0.0);
01524 
01525     glViewport(0, 0, view_width, view_height);
01526 }
01527 
01529 void print_usage(void)
01530 {
01531     cerr << "usage: alternaria-gen OPTIONS\n";
01532     cerr << "where OPTIONS is one or more of the following:\n";
01533     opts->print(cerr, 33);
01534 }
01535 
01537 void process_help_opt(void)
01538 {   
01539     print_usage();
01540     clean_up();
01541     exit(EXIT_SUCCESS);
01542 }
01543 
01545 void process_version_opt(void)
01546 {
01547     cout << ALTERNARIA_PACKAGE_STRING << "\n";
01548     clean_up();
01549     exit(EXIT_SUCCESS);
01550 }
01551 
01553 void process_options_opt(const char* arg) throw (Arg_error)
01554 {
01555     if (!arg)
01556     {
01557         throw Arg_error("Option 'options' requires an argument");
01558     }
01559     try
01560     {
01561         opts->process(arg);
01562     }
01563     catch (IO_error e)
01564     {
01565         throw Arg_error(e.get_msg());
01566     }
01567 }
01568 
01570 void process_seed_opt(const char* arg) throw (Arg_error)
01571 {
01572     if (!arg)
01573     {
01574         throw Arg_error("Option 'seed' requires an argument");
01575     }
01576     if (sscanf(arg, "%u", &seed) != 1)
01577     {
01578         throw Arg_error("Option 'seed' must be a non-negative integer");
01579     }
01580 }
01581 
01583 void process_apical_hypha_length_opt(const char* arg) throw (Arg_error)
01584 {
01585     float mu, sigma, min, max;
01586 
01587     if (!arg)
01588     {
01589         throw Arg_error("Option 'apical-hypha-length' requires an argument");
01590     }
01591     if (sscanf(arg, "%f,%f,%f,%f", &mu, &sigma, &min, &max) != 4)
01592     {
01593         throw Arg_error("Option 'apical-hypha-length' has format mu,sigma,min,max");
01594     }
01595     try
01596     {
01597         apical_hypha_d->set_length(mu, sigma, min, max);
01598     }
01599     catch (Arg_error e)
01600     {
01601         ostringstream ost;
01602         ost << "Option 'apical-hypha-length': " << e.get_msg();
01603         throw Arg_error(ost.str());
01604     }
01605 }
01606 
01608 void process_lateral_hypha_length_opt(const char* arg) throw (Arg_error)
01609 {
01610     float mu, sigma, min, max;
01611 
01612     if (!arg)
01613     {
01614         throw Arg_error("Option 'lateral-hypha-length' requires an argument");
01615     }
01616     if (sscanf(arg, "%f,%f,%f,%f", &mu, &sigma, &min, &max) != 4)
01617     {
01618         throw Arg_error("Option 'lateral-hypha-length' has format mu,sigma,min,max");
01619     }
01620     try
01621     {
01622         lateral_hypha_1_d->set_length(mu, sigma, min, max);
01623         lateral_hypha_n_d->set_length(mu, sigma, min, max);
01624     }
01625     catch (Arg_error e)
01626     {
01627         ostringstream ost;
01628         ost << "Option 'lateral-hypha-length': " << e.get_msg();
01629         throw Arg_error(ost.str());
01630     }
01631 }
01632 
01634 void process_apical_hypha_width_opt(const char* arg) throw (Arg_error)
01635 {
01636     float mu, sigma, min, max;
01637 
01638     if (!arg)
01639     {
01640         throw Arg_error("Option 'apical-hypha-width' requires an argument");
01641     }
01642     if (sscanf(arg, "%f,%f,%f,%f", &mu, &sigma, &min, &max) != 4)
01643     {
01644         throw Arg_error("Option 'apical-hypha-width' has format mu,sigma,min,max");
01645     }
01646     try
01647     {
01648         apical_hypha_d->set_width(mu, sigma, min, max);
01649     }
01650     catch (Arg_error e)
01651     {
01652         ostringstream ost;
01653         ost << "Option 'apical-hypha-width': " << e.get_msg();
01654         throw Arg_error(ost.str());
01655     }
01656 }
01657 
01659 void process_lateral_hypha_width_opt(const char* arg) throw (Arg_error)
01660 {
01661     float mu, sigma, min, max;
01662 
01663     if (!arg)
01664     {
01665         throw Arg_error("Option 'lateral-hypha-width' requires an argument");
01666     }
01667     if (sscanf(arg, "%f,%f,%f,%f", &mu, &sigma, &min, &max) != 4)
01668     {
01669         throw Arg_error("Option 'lateral-hypha-width' has format mu,sigma,min,max");
01670     }
01671     try
01672     {
01673         lateral_hypha_1_d->set_width(mu, sigma, min, max);
01674         lateral_hypha_n_d->set_width(mu, sigma, min, max);
01675     }
01676     catch (Arg_error e)
01677     {
01678         ostringstream ost;
01679         ost << "Option 'lateral-hypha-width': " << e.get_msg();
01680         throw Arg_error(ost.str());
01681     }
01682 }
01683 
01685 void process_apical_hypha_theta_opt(const char* arg) throw (Arg_error)
01686 {
01687     float mu, sigma, min, max;
01688 
01689     if (!arg)
01690     {
01691         throw Arg_error("Option 'apical-hypha-theta' requires an argument");
01692     }
01693     if (sscanf(arg, "%f,%f,%f,%f", &mu, &sigma, &min, &max) != 4)
01694     {
01695         throw Arg_error("Option 'apical-hypha-theta' has format mu,sigma,min,max");
01696     }
01697     try
01698     {
01699         apical_hypha_d->set_theta(mu, sigma, min, max);
01700     }
01701     catch (Arg_error e)
01702     {
01703         ostringstream ost;
01704         ost << "Option 'apical-hypha-theta': " << e.get_msg();
01705         throw Arg_error(ost.str());
01706     }
01707 }
01708 
01710 void process_lateral_hypha_1_theta_opt(const char* arg) throw (Arg_error)
01711 {
01712     float mu, sigma, min, max;
01713 
01714     if (!arg)
01715     {
01716         throw Arg_error("Option 'lateral-hypha-1-theta' requires an argument");
01717     }
01718     if (sscanf(arg, "%f,%f,%f,%f", &mu, &sigma, &min, &max) != 4)
01719     {
01720         throw Arg_error("Option 'lateral-hypha-1-theta' has format mu,sigma,min,max");
01721     }
01722     try
01723     {
01724         lateral_hypha_1_d->set_theta(mu, sigma, min, max);
01725     }
01726     catch (Arg_error e)
01727     {
01728         ostringstream ost;
01729         ost << "Option 'lateral-hypha-1-theta': " << e.get_msg();
01730         throw Arg_error(ost.str());
01731     }
01732 }
01733 
01735 void process_lateral_hypha_n_theta_opt(const char* arg) throw (Arg_error)
01736 {
01737     float mu, sigma, min, max;
01738 
01739     if (!arg)
01740     {
01741         throw Arg_error("Option 'lateral-hypha-n-theta' requires an argument");
01742     }
01743     if (sscanf(arg, "%f,%f,%f,%f", &mu, &sigma, &min, &max) != 4)
01744     {
01745         throw Arg_error("Option 'lateral-hypha-n-theta' has format mu,sigma,min,max");
01746     }
01747     try
01748     {
01749         lateral_hypha_n_d->set_theta(mu, sigma, min, max);
01750     }
01751     catch (Arg_error e)
01752     {
01753         ostringstream ost;
01754         ost << "Option 'lateral-hypha-n-theta': " << e.get_msg();
01755         throw Arg_error(ost.str());
01756     }
01757 }
01758 
01760 void process_hypha_psi_opt(const char* arg) throw (Arg_error)
01761 {
01762     float min, max;
01763 
01764     if (!arg)
01765     {
01766         throw Arg_error("Option 'hypha-psi' requires an argument");
01767     }
01768     if (sscanf(arg, "%f,%f", &min, &max) != 2)
01769     {
01770         throw Arg_error("Option 'hypha-psi' has format min,max");
01771     }
01772     try
01773     {
01774         apical_hypha_d->set_psi(min, max);
01775         lateral_hypha_1_d->set_psi(min, max);
01776         lateral_hypha_n_d->set_psi(min, max);
01777     }
01778     catch (Arg_error e)
01779     {
01780         ostringstream ost;
01781         ost << "Option 'hypha-psi': " << e.get_msg();
01782         throw Arg_error(ost.str());
01783     }
01784 }
01785 
01787 void process_hypha_opacity_opt(const char* arg) throw (Arg_error)
01788 {
01789     float mu, sigma, min, max;
01790 
01791     if (!arg)
01792     {
01793         throw Arg_error("Option 'hypha-opacity' requires an argument");
01794     }
01795     if (sscanf(arg, "%f,%f,%f,%f", &mu, &sigma, &min, &max) != 4)
01796     {
01797         throw Arg_error("Option 'hypha-opacity' has format mu,sigma,min,max");
01798     }
01799     try
01800     {
01801         apical_hypha_d->set_opacity(mu, sigma, min, max);
01802         lateral_hypha_1_d->set_opacity(mu, sigma, min, max);
01803         lateral_hypha_n_d->set_opacity(mu, sigma, min, max);
01804     }
01805     catch (Arg_error e)
01806     {
01807         ostringstream ost;
01808         ost << "Option 'hypha-opacity': " << e.get_msg();
01809         throw Arg_error(ost.str());
01810     }
01811 }
01812 
01814 void process_lateral_hypha_dist_opt(const char* arg) throw (Arg_error)
01815 {
01816     float mu, sigma, min, max;
01817 
01818     if (!arg)
01819     {
01820         throw Arg_error("Option 'lateral-hypha-dist' requires an argument");
01821     }
01822     if (sscanf(arg, "%f,%f,%f,%f", &mu, &sigma, &min, &max) != 4)
01823     {
01824         throw Arg_error("Option 'lateral-hypha-dist' has format mu,sigma,min,max");
01825     }
01826     try
01827     {
01828         lateral_hypha_1_d->set_lat_dist(mu, sigma, min, max);
01829         lateral_hypha_n_d->set_lat_dist(mu, sigma, min, max);
01830     }
01831     catch (Arg_error e)
01832     {
01833         ostringstream ost;
01834         ost << "Option 'lateral-hypha-dist': " << e.get_msg();
01835         throw Arg_error(ost.str());
01836     }
01837 }
01838 
01840 void process_spore_length_opt(const char* arg) throw (Arg_error)
01841 {
01842     float mu, sigma, min, max;
01843 
01844     if (!arg)
01845     {
01846         throw Arg_error("Option 'spore-length' requires an argument");
01847     }
01848     if (sscanf(arg, "%f,%f,%f,%f", &mu, &sigma, &min, &max) != 4)
01849     {
01850         throw Arg_error("Option 'spore-length' has format mu,sigma,min,max");
01851     }
01852     try
01853     {
01854         spore_d->set_length(mu, sigma, min, max);
01855     }
01856     catch (Arg_error e)
01857     {
01858         ostringstream ost;
01859         ost << "Option 'spore-length': " << e.get_msg();
01860         throw Arg_error(ost.str());
01861     }
01862 }
01863 
01865 void process_spore_width_opt(const char* arg) throw (Arg_error)
01866 {
01867     float mu, sigma, min, max;
01868 
01869     if (!arg)
01870     {
01871         throw Arg_error("Option 'spore-width' requires an argument");
01872     }
01873     if (sscanf(arg, "%f,%f,%f,%f", &mu, &sigma, &min, &max) != 4)
01874     {
01875         throw Arg_error("Option 'spore-width' has format mu,sigma,min,max");
01876     }
01877     try
01878     {
01879         spore_d->set_width(mu, sigma, min, max);
01880     }
01881     catch (Arg_error e)
01882     {
01883         ostringstream ost;
01884         ost << "Option 'spore-width': " << e.get_msg();
01885         throw Arg_error(ost.str());
01886     }
01887 }
01888 
01890 void process_spore_theta_opt(const char* arg) throw (Arg_error)
01891 {
01892     float mu, sigma, min, max;
01893 
01894     if (!arg)
01895     {
01896         throw Arg_error("Option 'spore-theta' requires an argument");
01897     }
01898     if (sscanf(arg, "%f,%f,%f,%f", &mu, &sigma, &min, &max) != 4)
01899     {
01900         throw Arg_error("Option 'spore-theta' has format mu,sigma,min,max");
01901     }
01902     try
01903     {
01904         spore_d->set_theta(mu, sigma, min, max);
01905     }
01906     catch (Arg_error e)
01907     {
01908         ostringstream ost;
01909         ost << "Option 'spore-theta': " << e.get_msg();
01910         throw Arg_error(ost.str());
01911     }
01912 }
01913 
01915 void process_spore_psi_opt(const char* arg) throw (Arg_error)
01916 {
01917     float min, max;
01918 
01919     if (!arg)
01920     {
01921         throw Arg_error("Option 'spore-psi' requires an argument");
01922     }
01923     if (sscanf(arg, "%f,%f", &min, &max) != 2)
01924     {
01925         throw Arg_error("Option 'spore-psi' has format min,max");
01926     }
01927     try
01928     {
01929         spore_d->set_psi(min, max);
01930     }
01931     catch (Arg_error e)
01932     {
01933         ostringstream ost;
01934         ost << "Option 'spore-psi': " << e.get_msg();
01935         throw Arg_error(ost.str());
01936     }
01937 }
01938 
01940 void process_spore_opacity_opt(const char* arg) throw (Arg_error)
01941 {
01942     float mu, sigma, min, max;
01943 
01944     if (!arg)
01945     {
01946         throw Arg_error("Option 'spore-opacity' requires an argument");
01947     }
01948     if (sscanf(arg, "%f,%f,%f,%f", &mu, &sigma, &min, &max) != 4)
01949     {
01950         throw Arg_error("Option 'spore-opacity' has format mu,sigma,min,max");
01951     }
01952     try
01953     {
01954         spore_d->set_opacity(mu, sigma, min, max);
01955     }
01956     catch (Arg_error e)
01957     {
01958         ostringstream ost;
01959         ost << "Option 'spore-opacity': " << e.get_msg();
01960         throw Arg_error(ost.str());
01961     }
01962 }
01963 
01965 void process_psf_alpha_opt(const char* arg) throw (Arg_error)
01966 {
01967     float mu, sigma, min, max;
01968 
01969     if (!arg)
01970     {
01971         throw Arg_error("Option 'psf-alpha' requires an argument");
01972     }
01973     if (sscanf(arg, "%f,%f,%f,%f", &mu, &sigma, &min, &max) != 4)
01974     {
01975         throw Arg_error("Option 'psf-alpha' has format mu,sigma,min,max");
01976     }
01977     try
01978     {
01979         psf_d->set_alpha(mu, sigma, min, max);
01980     }
01981     catch (Arg_error e)
01982     {
01983         ostringstream ost;
01984         ost << "Option 'psf-alpha': " << e.get_msg();
01985         throw Arg_error(ost.str());
01986     }
01987 }
01988 
01990 void process_psf_beta_opt(const char* arg) throw (Arg_error)
01991 {
01992     float mu, sigma, min, max;
01993 
01994     if (!arg)
01995     {
01996         throw Arg_error("Option 'psf-beta' requires an argument");
01997     }
01998     if (sscanf(arg, "%f,%f,%f,%f", &mu, &sigma, &min, &max) != 4)
01999     {
02000         throw Arg_error("Option 'psf-beta' has format mu,sigma,min,max");
02001     }
02002     try
02003     {
02004         psf_d->set_beta(mu, sigma, min, max);
02005     }
02006     catch (Arg_error e)
02007     {
02008         ostringstream ost;
02009         ost << "Option 'psf-beta': " << e.get_msg();
02010         throw Arg_error(ost.str());
02011     }
02012 }
02013 
02015 void process_psf_gamma_opt(const char* arg) throw (Arg_error)
02016 {
02017     float mu, sigma, min, max;
02018 
02019     if (!arg)
02020     {
02021         throw Arg_error("Option 'psf-gamma' requires an argument");
02022     }
02023     if (sscanf(arg, "%f,%f,%f,%f", &mu, &sigma, &min, &max) != 4)
02024     {
02025         throw Arg_error("Option 'psf-gamma' has format mu,sigma,min,max");
02026     }
02027     try
02028     {
02029         psf_d->set_gamma(mu, sigma, min, max);
02030     }
02031     catch (Arg_error e)
02032     {
02033         ostringstream ost;
02034         ost << "Option 'psf-gamma': " << e.get_msg();
02035         throw Arg_error(ost.str());
02036     }
02037 }
02038 
02040 void process_img_bg_opt(const char* arg) throw (Arg_error)
02041 {
02042     float mu, sigma, min, max;
02043 
02044     if (!arg)
02045     {
02046         throw Arg_error("Option 'img-bg' requires an argument");
02047     }
02048     if (sscanf(arg, "%f,%f,%f,%f", &mu, &sigma, &min, &max) != 4)
02049     {
02050         throw Arg_error("Option 'img-bg' has format mu,sigma,min,max");
02051     }
02052     try
02053     {
02054         imaging_d->set_bg(mu, sigma, min, max);
02055     }
02056     catch (Arg_error e)
02057     {
02058         ostringstream ost;
02059         ost << "Option 'img-bg': " << e.get_msg();
02060         throw Arg_error(ost.str());
02061     }
02062 }
02063 
02065 void process_levels_p_opt(const char* arg) throw (Arg_error)
02066 {
02067     float p;
02068 
02069     if (!arg)
02070     {
02071         throw Arg_error("Option 'levels-p' requires an argument");
02072     }
02073     if (sscanf(arg, "%f", &p) != 1)
02074     {
02075         throw Arg_error("Option 'levels-p' must be in a number in (0,1)");
02076     }
02077     try
02078     {
02079         alt_d->set_num_levels_p(p);
02080     }
02081     catch (Arg_error e)
02082     {
02083         ostringstream ost;
02084         ost << "Option 'levels-p': " << e.get_msg();
02085         throw Arg_error(ost.str());
02086     }
02087 }
02088 
02090 void process_structs_p_opt(const char* arg) throw (Arg_error)
02091 {
02092     float spore_p, apical_hypha_p, lateral_hypha_1_p, lateral_hypha_n_p;
02093 
02094     if (!arg)
02095     {
02096         throw Arg_error("Option 'structs-p' requires an argument");
02097     }
02098     if (sscanf(arg, "%f,%f,%f,%f", &spore_p, &apical_hypha_p, &lateral_hypha_1_p, &lateral_hypha_n_p) != 4)
02099     {
02100         throw Arg_error("Option 'structs-p' has format spore,apical-hypha,lateral-hypha-1,lateral-hypha-n");
02101     }
02102     try
02103     {
02104         alt_d->set_structure_p(spore_p, apical_hypha_p, lateral_hypha_1_p,
02105                 lateral_hypha_n_p);
02106     }
02107     catch (Arg_error e)
02108     {
02109         ostringstream ost;
02110         ost << "Option 'structs-p': " << e.get_msg();
02111         throw Arg_error(ost.str());
02112     }
02113 }
02114 
02116 void process_img_in_opt(const char* arg) throw (Arg_error)
02117 {
02118     if (!arg)
02119     {
02120         throw Arg_error("Option 'img-in' requires an argument");
02121     }
02122     img_in_fname = arg;
02123 }
02124 
02126 void process_img_out_opt(const char* arg) throw (Arg_error)
02127 {
02128     if (!arg)
02129     {
02130         throw Arg_error("Option 'img-out' requires an argument");
02131     }
02132     img_out_fname = arg;
02133 }
02134 
02136 void process_psf_in_opt(const char* arg) throw (Arg_error)
02137 {
02138     if (!arg)
02139     {
02140         throw Arg_error("Option 'psf-in' requires an argument");
02141     }
02142     psf_in_fname = arg;
02143 }
02144 
02146 void process_psf_out_opt(const char* arg) throw (Arg_error)
02147 {
02148     if (!arg)
02149     {
02150         throw Arg_error("Option 'psf-out' requires an argument");
02151     }
02152     psf_out_fname = arg;
02153 }
02154 
02156 void process_alt_in_opt(const char* arg) throw (Arg_error)
02157 {
02158     if (!arg)
02159     {
02160         throw Arg_error("Option 'alt-in' requires an argument");
02161     }
02162     alt_in_fname = arg;
02163 }
02164 
02166 void process_alt_out_opt(const char* arg) throw (Arg_error)
02167 {
02168     if (!arg)
02169     {
02170         throw Arg_error("Option 'alt-out' requires an argument");
02171     }
02172     alt_out_fname = arg;
02173 }
02174 
02176 void process_scene_fmt_opt(const char* arg) throw (Arg_error)
02177 {
02178     if (!arg)
02179     {
02180         throw Arg_error("Option 'scene-fmt' requires an argument");
02181     }
02182     alt_scene_fmt = arg;
02183 }
02184 
02186 void process_scene_size_opt(const char* arg) throw (Arg_error)
02187 {
02188     uint32_t ncols, nrows, nimgs;
02189 
02190     if (!arg)
02191     {
02192         throw Arg_error("Option 'scene-size' requires an argument");
02193     }
02194     if (sscanf(arg, "%u,%u,%u", &ncols, &nrows, &nimgs) != 3)
02195     {
02196         throw Arg_error("Option 'scene-size' has format ncols,nrows,nimgs");
02197     }
02198     try
02199     {
02200         img_window->set(0, 0, 0, ncols, nrows, nimgs);
02201     }
02202     catch (Arg_error e)
02203     {
02204         ostringstream ost;
02205         ost << "Option 'scene-size': " << e.get_msg();
02206         throw Arg_error(ost.str());
02207     }
02208 }
02209 
02211 void process_scene_scale_opt(const char* arg) throw (Arg_error)
02212 {
02213     float x, y, z;
02214 
02215     if (!arg)
02216     {
02217         throw Arg_error("Option 'scene-scale' requires an argument");
02218     }
02219     if (sscanf(arg, "%f,%f,%f", &x, &y, &z) != 3)
02220     {
02221         throw Arg_error("Option 'scene-scale' has format x,y,z");
02222     }
02223     try
02224     {
02225         img_scale->set(x, y, z);
02226     }
02227     catch (Arg_error e)
02228     {
02229         ostringstream ost;
02230         ost << "Option 'scene-scale': " << e.get_msg();
02231         throw Arg_error(ost.str());
02232     }
02233 }
02234 
02236 void process_psf_fmt_opt(const char* arg) throw (Arg_error)
02237 {
02238     if (!arg)
02239     {
02240         throw Arg_error("Option 'psf-fmt' requires an argument");
02241     }
02242     psf_h_fmt = arg;
02243 }
02244 
02246 void process_num_structs_opt(const char* arg) throw (Arg_error)
02247 {
02248     if (!arg)
02249     {
02250         throw Arg_error("Option 'num-structs' requires an argument");
02251     }
02252     if (sscanf(arg, "%u", &num_structs) != 1)
02253     {
02254         throw Arg_error("Option 'num-structs' must be an integer");
02255     }
02256 }
02257 
02259 void process_interactive_opt() throw (Arg_error)
02260 {
02261     interactive = true;
02262 }
02263 
02265 void process_view_size_opt(const char* arg) throw (Arg_error)
02266 {
02267     int32_t w, h;
02268 
02269     if (!arg)
02270     {
02271         throw Arg_error("Option 'view-size' requires an argument");
02272     }
02273     if (sscanf(arg, "%d,%d", &w, &h) != 2)
02274     {
02275         throw Arg_error("Option 'view-size' has format width,height");
02276     }
02277     if (w <= 0 || h <= 0)
02278     {
02279         throw Arg_error("Option 'view-size' must have width,height > 0");
02280     }
02281     view_width = (uint32_t)w;
02282     view_height = (uint32_t)h;
02283 }
02284 
02286 void process_glasses_opt(const char* arg) throw (Arg_error)
02287 {
02288     if (!arg)
02289     {
02290         throw Arg_error("Option 'glasses' requires an argument");
02291     }
02292     if (strcmp("red-blue", arg) == 0)
02293         glasses_type = REDBLUE;
02294     else if (strcmp("red-green", arg) == 0)
02295         glasses_type = REDGREEN;
02296     else if (strcmp("red-cyan", arg) == 0)
02297         glasses_type = REDCYAN;
02298     else if (strcmp("blue-red", arg) == 0)
02299         glasses_type = BLUERED;
02300     else if (strcmp("green-red", arg) == 0)
02301         glasses_type = GREENRED;
02302     else if (strcmp("cyan-red", arg) == 0)
02303         glasses_type = CYANRED;
02304     else
02305     {
02306         throw Arg_error("Invalid 'glasses' type");
02307     }
02308 }
02309 
02311 void process_capture_opt(const char* arg) throw (Arg_error)
02312 {
02313     if (!arg)
02314     {
02315         throw Arg_error("Option 'capture' requires an argument");
02316     }
02317     capture_fmt = arg;
02318 }
02319 
02321 void process_base_level_opt(const char* arg) throw (Arg_error)
02322 {
02323     if (!arg)
02324     {
02325         throw Arg_error("Option 'base-level' requires an argument");
02326     }
02327     if (sscanf(arg, "%u", &base_level) != 1)
02328     {
02329         throw Arg_error("Option 'base-level' must be >= 0");
02330     }
02331 }
02332 
02334 void init_options()
02335 {
02336     using jwscxx::base::Option_no_arg;
02337     using jwscxx::base::Option_with_arg;
02338 
02339     const char* l_name;
02340     const char* desc;
02341 
02342     opts = new Options();
02343 
02344     l_name = "help";
02345     desc   = "Program usage";
02346     opts->add(new Option_no_arg('h', l_name, desc, process_help_opt));
02347 
02348     l_name = "version";
02349     desc   = "Program version.";
02350     opts->add(new Option_no_arg('v', l_name, desc, process_version_opt));
02351 
02352     l_name = "options";
02353     desc   = "Process a file of program options.";
02354     opts->add(new Option_with_arg(0, l_name, desc, process_options_opt));
02355 
02356     l_name = "interactive";
02357     desc   = "Show the generated Alternaria in an interactive GLUT/GL window.";
02358     opts->add(new Option_no_arg('i', l_name, desc, process_interactive_opt));
02359 
02360     l_name = "view-size";
02361     desc   = "Interactive window View size with format width,height. Default is 400,400.";
02362     opts->add(new Option_with_arg(0, l_name, desc, process_view_size_opt));
02363 
02364     l_name = "glasses";
02365     desc   = "Type of colored glasses for anaglyph mode in the interactive window. Possible left-right filter types include include red-blue, red-green, red-cyan, blue-red, green-red, cyan-red. Default is cyan-red.";
02366     opts->add(new Option_with_arg(0, l_name, desc, process_glasses_opt));
02367 
02368     l_name = "capture";
02369     desc   = "Printf-formatted file write captured view images to.";
02370     opts->add(new Option_with_arg(0, l_name, desc, process_capture_opt));
02371 
02372     l_name = "seed";
02373     desc   = "Random seed to use in srand(). Must be a non-negative integer.";
02374     opts->add(new Option_with_arg(0, l_name, desc, process_seed_opt));
02375 
02376     l_name = "img-in";
02377     desc   = "Imaging input file to read from.";
02378     opts->add(new Option_with_arg(0, l_name, desc, process_img_in_opt));
02379 
02380     l_name = "img-out";
02381     desc   = "Imaging output file to write to.";
02382     opts->add(new Option_with_arg(0, l_name, desc, process_img_out_opt));
02383 
02384     l_name = "psf-in";
02385     desc   = "PSF input file to read from.";
02386     opts->add(new Option_with_arg(0, l_name, desc, process_psf_in_opt));
02387 
02388     l_name = "psf-out";
02389     desc   = "PSF output file to write to.";
02390     opts->add(new Option_with_arg(0, l_name, desc, process_psf_out_opt));
02391 
02392     l_name = "alt-in";
02393     desc   = "Alternaria input file to read from.";
02394     opts->add(new Option_with_arg(0, l_name, desc, process_alt_in_opt));
02395 
02396     l_name = "alt-out";
02397     desc   = "Alternaria output file to write to.";
02398     opts->add(new Option_with_arg(0, l_name, desc, process_alt_out_opt));
02399 
02400     l_name = "scene-fmt";
02401     desc   = "Printf-formatted file name for the optically sectioned scene. Must contain one integer conversion";
02402     opts->add(new Option_with_arg(0, l_name, desc, process_scene_fmt_opt));
02403 
02404     l_name = "scene-scale";
02405     desc   = "Number of alternaria world units per image pixel. Has format x,y,z.";
02406     opts->add(new Option_with_arg(0, l_name, desc, process_scene_scale_opt));
02407 
02408     l_name = "scene-size";
02409     desc   = "Width, height, and number of images to write the optically sectioned scene to. Has format ncols,nrows,nimgs.";
02410     opts->add(new Option_with_arg(0, l_name, desc, process_scene_size_opt));
02411 
02412     l_name = "psf-fmt";
02413     desc   = "Printf-formatted file name for the optically sectioned PSF. Must contain one integer conversion.";
02414     opts->add(new Option_with_arg(0, l_name, desc, process_psf_fmt_opt));
02415 
02416     l_name = "num-structs";
02417     desc   = "Number of structure elements to generate in the Alternaria. Must be an integer.";
02418     opts->add(new Option_with_arg(0, l_name, desc, process_num_structs_opt));
02419 
02420     l_name = "apical-hypha-length";
02421     desc   = "Length of an apical hypha. Has argument format mu,sigma,min,max.";
02422     opts->add(new Option_with_arg(0, l_name, desc, 
02423                 process_apical_hypha_length_opt));
02424 
02425     l_name = "lateral-hypha-length";
02426     desc   = "Length of a lateral hypha. Has argument format mu,sigma,min,max.";
02427     opts->add(new Option_with_arg(0, l_name, desc, 
02428                 process_lateral_hypha_length_opt));
02429 
02430     l_name = "apical-hypha-width";
02431     desc   = "Width of an apical hypha. Has argument format mu,sigma,min,max.";
02432     opts->add(new Option_with_arg(0, l_name, desc, 
02433                 process_apical_hypha_width_opt));
02434 
02435     l_name = "lateral-hypha-width";
02436     desc   = "Width of a lateral hypha. Has argument format mu,sigma,min,max.";
02437     opts->add(new Option_with_arg(0, l_name, desc, 
02438                 process_lateral_hypha_width_opt));
02439 
02440     l_name = "apical-hypha-theta";
02441     desc   = "Theta Euler angle of an apical hypha. Has argument format mu,sigma,min,max.";
02442     opts->add(new Option_with_arg(0, l_name, desc, 
02443                 process_apical_hypha_theta_opt));
02444 
02445     l_name = "lateral-hypha-1-theta";
02446     desc   = "Theta Euler angle of a lateral hypha at level 1. Has argument format mu,sigma,min,max.";
02447     opts->add(new Option_with_arg(0, l_name, desc, 
02448                 process_lateral_hypha_1_theta_opt));
02449 
02450     l_name = "lateral-hypha-n-theta";
02451     desc   = "Theta Euler angle of a lateral hypha at level > 1. Has argument format mu,sigma,min,max.";
02452     opts->add(new Option_with_arg(0, l_name, desc, 
02453                 process_lateral_hypha_n_theta_opt));
02454 
02455     l_name = "hypha-psi";
02456     desc   = "Psi Euler angle of a hypha. Has argument format mu,sigma,min,max.";
02457     opts->add(new Option_with_arg(0, l_name, desc, process_hypha_psi_opt));
02458 
02459     l_name = "hypha-opacity";
02460     desc   = "Opacity of a hypha. Has argument format mu,sigma,min,max.";
02461     opts->add(new Option_with_arg(0, l_name, desc, process_hypha_opacity_opt));
02462 
02463     l_name = "lateral-hypha-dist";
02464     desc   = "Distance of a lateral hypha from its parent. Has argument format mu,sigma,min,max.";
02465     opts->add(new Option_with_arg(0, l_name, desc, 
02466                 process_lateral_hypha_dist_opt));
02467 
02468     l_name = "spore-width";
02469     desc   = "Width of a spore. Has argument format mu,sigma,min,max.";
02470     opts->add(new Option_with_arg(0, l_name, desc, process_spore_width_opt));
02471 
02472     l_name = "spore-length";
02473     desc   = "Length of a spore. Has argument format mu,sigma,min,max.";
02474     opts->add(new Option_with_arg(0, l_name, desc, process_spore_length_opt));
02475 
02476     l_name = "spore-theta";
02477     desc   = "Theta Euler angle of a spore. Has argument format mu,sigma,min,max.";
02478     opts->add(new Option_with_arg(0, l_name, desc, process_spore_theta_opt));
02479 
02480     l_name = "spore-psi";
02481     desc   = "Psi Euler angle of a spore. Has argument format min,max.";
02482     opts->add(new Option_with_arg(0, l_name, desc, process_spore_psi_opt));
02483 
02484     l_name = "spore-opacity";
02485     desc   = "Opacity of a spore. Has argument format mu,sigma,min,max.";
02486     opts->add(new Option_with_arg(0, l_name, desc, process_spore_opacity_opt));
02487 
02488     l_name = "psf-alpha";
02489     desc   = "PSF alpha parameter. Has argument format mu,sigma,min,max.";
02490     opts->add(new Option_with_arg(0, l_name, desc, process_psf_alpha_opt));
02491 
02492     l_name = "psf-beta";
02493     desc   = "PSF beta parameter. Has argument format mu,sigma,min,max.";
02494     opts->add(new Option_with_arg(0, l_name, desc, process_psf_beta_opt));
02495 
02496     l_name = "psf-gamma";
02497     desc   = "PSF gamma parameter. Has argument format mu,sigma,min,max.";
02498     opts->add(new Option_with_arg(0, l_name, desc, process_psf_gamma_opt));
02499 
02500     l_name = "img-bg";
02501     desc   = "Image background parameter. Has argument format mu,sigma,min,max.";
02502     opts->add(new Option_with_arg(0, l_name, desc, process_img_bg_opt));
02503 
02504     l_name = "levels-p";
02505     desc   = "Geometric distribution parameter over growth levels. Must be in (0,1)";
02506     opts->add(new Option_with_arg(0, l_name, desc, process_levels_p_opt));
02507 
02508     l_name = "structs-p";
02509     desc   = "Distribution over structure type. Has argument format spore,apical-hypha,lateral-hypha. All must sum to 1.";
02510     opts->add(new Option_with_arg(0, l_name, desc, process_structs_p_opt));
02511 
02512     l_name = "base-level";
02513     desc   = "Base level for the root Structure. Must be >= 0.";
02514     opts->add(new Option_with_arg(0, l_name, desc, process_base_level_opt));
02515 }
02516 
02517 
02518 void* operator new (size_t s) throw (std::bad_alloc)
02519 {
02520     return malloc(s);
02521 }
02522 
02523 
02524 void operator delete (void* ptr) throw ()
02525 {
02526     if (ptr)
02527         free(ptr);
02528 }
02529 
02530 
02531 
02532 
02534 int main(int argc, char** argv)
02535 {
02536     init_options();
02537 
02538     try
02539     {
02540         img_window        = new Imaging_window();
02541         img_scale         = new Imaging_scale();
02542         padding           = new PSF_padding();
02543         imaging_d         = new Imaging_model_density();
02544         psf_d             = new PSF_model_density();
02545         spore_d           = new Spore_density();
02546         apical_hypha_d    = new Apical_hypha_density();
02547         lateral_hypha_1_d = new Lateral_hypha_density();
02548         lateral_hypha_n_d = new Lateral_hypha_density();
02549         alt_d             = new Alternaria_density();
02550 
02551         img_window->set(0, 0, 0, NUM_SCENE_COLS, NUM_SCENE_ROWS, 
02552                 NUM_SCENE_IMGS);
02553 
02554         spore_d->set_centroid_x(CENTROID_MIN, CENTROID_MAX);
02555         spore_d->set_centroid_y(CENTROID_MIN, CENTROID_MAX);
02556         spore_d->set_centroid_z(CENTROID_MIN, CENTROID_MAX);
02557 
02558         apical_hypha_d->set_centroid_x(CENTROID_MIN, CENTROID_MAX);
02559         apical_hypha_d->set_centroid_y(CENTROID_MIN, CENTROID_MAX);
02560         apical_hypha_d->set_centroid_z(CENTROID_MIN, CENTROID_MAX);
02561 
02562         lateral_hypha_1_d->set_centroid_x(CENTROID_MIN, CENTROID_MAX);
02563         lateral_hypha_1_d->set_centroid_y(CENTROID_MIN, CENTROID_MAX);
02564         lateral_hypha_1_d->set_centroid_z(CENTROID_MIN, CENTROID_MAX);
02565 
02566         lateral_hypha_n_d->set_centroid_x(CENTROID_MIN, CENTROID_MAX);
02567         lateral_hypha_n_d->set_centroid_y(CENTROID_MIN, CENTROID_MAX);
02568         lateral_hypha_n_d->set_centroid_z(CENTROID_MIN, CENTROID_MAX);
02569 
02570         opts->process(argc, argv); 
02571 
02572         std::srand(seed);
02573 
02574         // Sometimes the first few draws off the generator are always ~0.
02575         std::rand();
02576         std::rand();
02577         std::rand();
02578 
02579         if (img_in_fname)
02580         {
02581             imaging = new Imaging_model(img_in_fname, img_window, img_scale,
02582                     imaging_d);
02583         }
02584         else
02585         {
02586             imaging = imaging_d->sample(img_window, img_scale);
02587         }
02588 
02589         if (psf_in_fname)
02590         {
02591             psf = new PSF_model(psf_in_fname, padding, psf_d, imaging);
02592         }
02593         else
02594         {
02595             psf = psf_d->sample(padding, imaging);
02596         }
02597 
02598         if (alt_in_fname)
02599         {
02600             alternaria = new Alternaria(alt_in_fname, alt_d, spore_d,
02601                     apical_hypha_d, lateral_hypha_1_d, lateral_hypha_n_d);
02602         }
02603         else
02604         {
02605             float x = 0.5f*img_scale->get_x()*img_window->get_num_cols();
02606             float y = 0.5f*apical_hypha_d->sample_length();
02607             float z = 0.5f*img_scale->get_z()*img_window->get_num_imgs();
02608             alternaria = alt_d->sample(num_structs, x, y, z, JWSC_PI_2, 0, 
02609                     base_level, spore_d, apical_hypha_d, lateral_hypha_1_d, 
02610                     lateral_hypha_n_d);
02611         }
02612 
02613         if (interactive)
02614         {
02615             init_glut(argc, argv);
02616             init_gl();
02617             init_camera();
02618             init_modes();
02619             glutMainLoop();
02620         }
02621         else
02622         {
02623             if (img_out_fname)
02624             {
02625                 imaging->print(img_out_fname);
02626             }
02627             if (psf_out_fname)
02628             {
02629                 psf->print(psf_out_fname);
02630             }
02631             if (alt_out_fname)
02632             {
02633                 alternaria->print(alt_out_fname);
02634             }
02635             if (psf_h_fmt)
02636             {
02637                 psf->write_h(psf_h_fmt);
02638             }
02639             if (alt_scene_fmt)
02640             {
02641                 Alternaria_model* model = new Alternaria_model(*alternaria, 
02642                         psf, imaging);
02643                 model->write_scene(alt_scene_fmt, psf);
02644                 delete model;
02645             }
02646         }
02647     }
02648     catch (Exception e)
02649     {
02650         cerr << "alternaria_gen: ";
02651         e.print();
02652     }
02653 
02654     clean_up();
02655 
02656     return EXIT_SUCCESS;
02657 }