bugs: Advantages for incremental library separation by analogy with incremental
[Ale.git] / ui / ui.h
blob308395d2db1b59583400f1e611d3d75d0390fe23
1 // Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
2 // <dhilvert@ugcs.caltech.edu>
4 /* This file is part of the Anti-Lamenessing Engine.
6 The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 The Anti-Lamenessing Engine is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with the Anti-Lamenessing Engine; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #ifndef __ui_h__
22 #define __ui_h__
24 #include <cstring>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <stdarg.h>
29 #include <assert.h>
30 #include "../ale_pos.h"
31 #include "../config.h"
32 #if HAVE_TIME_H
33 #include <time.h>
34 #endif
35 #if HAVE_SYS_TIME_H
36 #include <sys/time.h>
37 #endif
39 #include <map>
42 * Time structures.
45 namespace d2 {
46 struct trans_multi;
47 typedef trans_multi transformation;
48 struct trans_abstract;
49 struct trans_single;
52 class ale_timer_t {
53 #if HAVE_GETTIMEOFDAY
54 struct timeval tv;
55 #else
56 time_t tt;
57 #endif
58 double total;
60 public:
62 ale_timer_t() {
63 total = 0;
66 void start() {
67 #if HAVE_GETTIMEOFDAY
68 gettimeofday(&tv, NULL);
69 #else
70 tt = time(NULL);
71 #endif
74 void stop() {
75 #if HAVE_GETTIMEOFDAY
76 timeval t;
78 gettimeofday(&t, NULL);
80 t.tv_sec -= tv.tv_sec;
81 t.tv_usec -= tv.tv_usec;
83 total += t.tv_sec + ((double) 1 / (double) 1000000) * t.tv_usec;
84 #else
85 time_t t = time(NULL);
86 t -= tt;
88 total += t;
89 #endif
92 double get_total() {
93 return total;
98 * User interface messages.
101 class ui_wo;
103 class ui {
104 private:
105 static ui *singleton;
108 * UI type
110 * 0. stream
111 * 1. tty
112 * 2. log
113 * 3. quiet
114 * 4. gl
115 * 5. auto
118 static int type;
120 static int output_performance_data;
122 protected:
125 * Data
128 FILE *ui_stream;
130 struct status_type {
131 enum {
133 * Special
136 UNDEFINED,
139 * Incremental rendering.
142 LOAD_FILE, EXPOSURE_PASS_1,
143 LODCLUSTER_CREATE, PREMATCH, ALIGN, GLOBAL_ALIGN, POSTMATCH,
144 EXPOSURE_PASS_2, RENDERA, RENDERD, RENDERO, WRITED,
145 WRITEO, FRAME_DONE, SET_DONE, MULTI,
148 * Irani-Peleg rendering.
151 IP_RENDER, IP_STEP_DONE, IP_UPDATE, IP_WRITE,
154 * 3D.
157 D3_CONTROL_POINT_SOLVE, D3_SUBDIVIDING_SPACE,
158 D3_UPDATING_OCCUPANCY, D3_RENDER
160 } code, orender_current;
162 int arender_current;
163 double match_value;
164 int onum;
165 int steps;
166 int steps_completed;
167 int step_type;
168 double exp_multiplier[3];
169 double perturb_size;
170 double align_lod;
171 unsigned int element_degree;
172 unsigned int total_degree;
173 unsigned int element_index;
174 unsigned int num_elements;
175 unsigned int frame_num;
176 unsigned int irani_peleg_stage;
177 unsigned int irani_peleg_step;
178 unsigned int irani_peleg_steps;
179 unsigned int secondary_frame_num;
180 unsigned int view_num;
181 unsigned int x_coordinate, y_coordinate;;
182 unsigned int filtering, focusing;
183 unsigned int space_num;
184 unsigned int total_spaces;
185 double cp_max_perturb;
186 double cp_min_perturb;
187 double cp_cur_perturb;
188 double cp_cur_error;
189 int cache;
191 status_type() {
192 code = UNDEFINED;
193 steps_completed = 0;
194 cache = 1;
196 for (int k = 0; k < 3; k++)
197 exp_multiplier[k] = 1;
199 element_degree = 0;
200 total_degree = 0;
201 element_index = 0;
202 num_elements = 0;
203 match_value = 0;
204 perturb_size = 0;
205 align_lod = 0;
207 } status;
210 * Performance data
213 ale_timer_t d2_align_sample;
214 ale_timer_t d2_align_sim;
215 ale_timer_t d2_incremental;
216 ale_timer_t d2_irani_peleg;
217 std::map<double,ale_timer_t> perturb_timers;
220 * Constructor
223 ui() {
224 ui_stream = stderr;
228 * Print function
231 virtual void printf(const char *format, ...) = 0;
234 * UI update function
237 virtual void update() = 0;
240 * Match format strings for textual UIs.
243 const char *format_string_ok() {
244 return " okay (%9.6f%% match)";
246 const char *format_string_no_match() {
247 return " no match (%9.6f%% match)";
249 const char *format_string_working() {
250 return " (%9.6f%% match)";
253 public:
256 * Handle options and other user input.
259 static void handle_input(int argc, const char *argv[], const char *package,
260 const char *short_version, const char *version);
262 static ui *get();
264 static void set_stream() {
265 assert(singleton == NULL);
266 type = 0;
269 static void set_tty() {
270 assert(singleton == NULL);
271 type = 1;
274 static void set_log() {
275 assert (singleton == NULL);
276 type = 2;
279 static void set_quiet() {
280 assert(singleton == NULL);
281 type = 3;
284 static void set_profile() {
285 output_performance_data = 1;
289 * Messages from the engine
292 virtual void identify_output(const char *name) {
293 printf("Output file will be '%s'.\n", name);
296 virtual void d2_align_sim_start() {
297 d2_align_sim.start();
300 virtual void d2_align_sim_stop() {
301 d2_align_sim.stop();
304 virtual void d2_align_sample_start() {
305 d2_align_sample.start();
308 virtual void d2_align_sample_stop() {
309 d2_align_sample.stop();
312 virtual void d2_incremental_start() {
313 d2_incremental.start();
316 virtual void d2_incremental_stop() {
317 d2_incremental.stop();
320 virtual void d2_irani_peleg_start() {
321 d2_irani_peleg.start();
324 virtual void d2_irani_peleg_stop() {
325 d2_irani_peleg.stop();
328 virtual void exp_multiplier(double m0, double m1, double m2) {
329 status.exp_multiplier[0] = m0;
330 status.exp_multiplier[1] = m1;
331 status.exp_multiplier[2] = m2;
334 void exp_multiplier(double mult[3]) {
335 exp_multiplier(mult[0], mult[1], mult[2]);
338 virtual void set_steps(int count, int type = 0) {
339 status.steps = count;
340 status.step_type = type;
343 virtual void set_steps_completed(int count) {
344 status.steps_completed = count;
347 virtual void set_match(double match) {
348 status.match_value = (1 - match) * 100;
349 update();
352 virtual void set_offset(d2::trans_single offset);
353 virtual void set_offset(d2::trans_multi offset);
355 virtual void gs_mo(ale_pos gs_mo) {
358 virtual void cache_status(unsigned int c) {
359 status.cache = c;
362 virtual void loading_file() {
363 status.code = status.LOAD_FILE;
364 update();
367 virtual void exposure_1() {
368 status.code = status.EXPOSURE_PASS_1;
369 update();
372 virtual void exposure_2() {
373 status.code = status.EXPOSURE_PASS_2;
374 update();
377 virtual void prematching() {
378 status.code = status.PREMATCH;
379 update();
382 virtual void postmatching() {
383 status.code = status.POSTMATCH;
384 update();
387 virtual void constructing_lod_clusters(ale_pos lod) {
388 status.code = status.LODCLUSTER_CREATE;
389 status.align_lod = lod;
390 update();
393 virtual void global_alignment(ale_pos perturb, ale_pos lod) {
394 status.perturb_size = perturb;
395 status.align_lod = lod;
396 status.code = status.GLOBAL_ALIGN;
397 update();
400 virtual void aligning(ale_pos perturb, ale_pos lod) {
401 perturb_timers[perturb].start();
402 status.perturb_size = perturb;
403 status.align_lod = lod;
404 status.code = status.ALIGN;
405 update();
408 virtual void multi() {
409 status.code = status.MULTI;
410 update();
413 virtual void following() {
416 virtual void set_orender_current(int num) {
417 status.onum = num;
418 if (num == 0)
419 status.orender_current = status.RENDERD;
420 else
421 status.orender_current = status.RENDERO;
424 virtual void set_arender_current() {
425 status.arender_current = 1;
428 virtual void clear_arender_current() {
429 status.arender_current = 0;
432 virtual void rendering() {
434 * Current alignment rendering tasks must complete
435 * before any current output rendering tasks can
436 * start.
438 if (status.arender_current) {
439 status.code = status.RENDERA;
440 status.arender_current = 0;
441 } else {
442 status.code = status.orender_current;
444 update();
447 virtual void writing_output(int num) {
448 status.onum = num;
449 if (num == 0)
450 status.code = status.WRITED;
451 else
452 status.code = status.WRITEO;
453 update();
456 virtual void d3_control_point_data(double max_perturbation, double min_perturbation, double cur_perturbation,
457 double current_error) {
458 status.cp_max_perturb = max_perturbation;
459 status.cp_min_perturb = min_perturbation;
460 status.cp_cur_perturb = cur_perturbation;
461 status.cp_cur_error = current_error;
462 update();
465 virtual void d3_control_point_step() {
466 printf(".");
467 update();
470 void set_frame_num(unsigned int num) {
471 status.frame_num = num;
474 virtual void d3_subdivision_status(unsigned int primary_frame, unsigned int secondary_frame,
475 unsigned int i, unsigned int j) {
476 status.code = status.D3_SUBDIVIDING_SPACE;
477 status.frame_num = primary_frame;
478 status.secondary_frame_num = secondary_frame;
479 status.y_coordinate = i;
480 status.x_coordinate = j;
482 update();
485 virtual void d3_total_spaces(int total_spaces) {
486 status.total_spaces = total_spaces;
489 virtual void d3_increment_spaces() {
490 status.total_spaces++;
493 virtual void d3_occupancy_status(int frame) {
494 status.code = status.D3_UPDATING_OCCUPANCY;
495 status.frame_num = frame;
496 status.space_num = 0;
497 update();
500 virtual void d3_increment_space_num() {
501 status.space_num++;
502 update();
505 virtual void d3_render_status(int filter, int focus, int frame, int view, int i, int j, int space) {
506 status.code = status.D3_RENDER;
508 status.filtering = filter;
509 status.focusing = focus;
511 status.frame_num = frame;
512 status.view_num = view;
513 status.y_coordinate = i;
514 status.x_coordinate = j;
516 status.space_num = space;
518 update();
523 * Informational output
526 virtual void ip_start() {
527 printf("Iterating Irani-Peleg");
530 virtual void refilter_start() {
531 printf("Re-filtering incremental results");
534 virtual void ip_frame_start(unsigned int num) {
535 status.code = status.IP_RENDER;
536 status.frame_num = num;
537 status.irani_peleg_stage = 0;
538 update();
541 virtual void ip_frame_simulate_start() {
542 status.code = status.IP_RENDER;
543 status.irani_peleg_stage = 1;
544 update();
547 virtual void ip_frame_correct_start() {
548 status.code = status.IP_RENDER;
549 status.irani_peleg_stage = 2;
550 update();
553 virtual void ip_update() {
554 status.code = status.IP_UPDATE;
555 update();
558 virtual void ip_write() {
559 status.code = status.IP_WRITE;
560 update();
563 void ip_step_start(int num, int total) {
564 status.irani_peleg_step = num;
565 status.irani_peleg_steps = total;
568 virtual void ip_step_done() {
569 status.code = status.IP_STEP_DONE;
570 printf(".");
573 virtual void ip_done() {
574 printf("\n");
577 virtual void refilter_done() {
578 printf(".\n");
581 virtual void original_frame_start(const char *name) {
582 status.code = status.UNDEFINED;
583 printf("Original Frame:\n");
584 printf(" '%s'", name);
587 virtual void original_frame_done() {
588 status.code = status.FRAME_DONE;
589 update();
592 virtual void supplemental_frame_start(const char *name) {
593 static int section_announced = 0;
595 if (!section_announced) {
596 printf("Supplemental Frames:\n");
597 section_announced = 1;
600 status.code = status.UNDEFINED;
601 status.steps_completed = 0;
602 printf(" '%s'", name);
605 virtual void supplemental_frame_done() {
606 status.code = status.FRAME_DONE;
607 update();
610 void alignment_degree_max(int degree_total) {
611 status.total_degree = degree_total;
612 status.element_degree = 0;
615 virtual void alignment_degree_complete(int degree) {
616 if (status.step_type == 1) {
617 status.steps_completed++;
618 printf("*");
620 status.element_degree = degree;
621 update();
624 void aligning_element(unsigned int index, unsigned int num) {
625 status.element_index = index;
626 status.num_elements = num;
627 update();
631 virtual void alignment_perturbation_level(ale_pos perturb, ale_pos lod) {
632 perturb_timers[status.perturb_size].stop();
633 perturb_timers[perturb].start();
634 status.perturb_size = perturb;
635 status.align_lod = lod;
636 if (status.step_type == 0) {
637 status.steps_completed++;
638 printf(".");
642 virtual void alignment_dims(unsigned int hr, unsigned int wr, unsigned int hi, unsigned int wi) {
645 virtual void start_multi_alignment_element(d2::trans_multi &tm) {
648 virtual void alignment_match_ok() {
649 status.code = status.UNDEFINED;
650 printf(format_string_ok(), status.match_value);
653 virtual void alignment_no_match() {
654 status.code = status.UNDEFINED;
655 printf(format_string_no_match(), status.match_value);
658 virtual void ale_2d_done(double value) {
659 status.code = status.UNDEFINED;
660 printf("Average match: %f%%", value);
661 status.code = status.SET_DONE;
662 update();
663 if (output_performance_data) {
664 printf("\n");
665 printf("Real time measurements\n");
666 printf("======================\n");
667 printf("\n");
668 printf("Alignment (sampling) : %f s\n", d2_align_sample.get_total());
669 printf("Alignment (checking) : %f s\n", d2_align_sim.get_total());
670 printf("Incremental rendering : %f s\n", d2_incremental.get_total());
671 printf("Irani-Peleg rendering : %f s\n", d2_irani_peleg.get_total());
672 printf("\n");
674 printf("Details (local alignment)\n");
675 printf("-------------------------\n");
677 int have_details = 0;
678 for (std::map<double,ale_timer_t>::iterator i = perturb_timers.begin();
679 i != perturb_timers.end(); i++) {
680 if (i->second.get_total() == 0.0
681 && i == perturb_timers.begin())
682 continue;
684 printf("Alignment (perturb %f): %f s\n",
685 i->first, i->second.get_total());
687 have_details = 1;
690 if (!have_details) {
691 printf("No local alignment performed.\n");
694 printf("\n");
698 virtual void d3_start() {
699 status.code = status.UNDEFINED;
700 printf("Rendering 3D");
701 update();
704 virtual void d3_control_point_solve() {
705 status.code = status.D3_CONTROL_POINT_SOLVE;
706 update();
709 virtual void d3_init_view_angle(double angle) {
710 status.code = status.UNDEFINED;
711 update();
714 virtual void d3_final_view_angle(double angle) {
715 status.code = status.UNDEFINED;
716 update();
719 virtual void d3_control_point_solve_done() {
720 status.code = status.UNDEFINED;
721 update();
724 virtual void d3_subdividing_space() {
725 status.code = status.D3_SUBDIVIDING_SPACE;
726 update();
729 virtual void d3_subdividing_space_done() {
730 status.code = status.UNDEFINED;
731 update();
734 virtual void d3_updating_occupancy() {
735 status.code = status.D3_UPDATING_OCCUPANCY;
736 update();
739 virtual void d3_updating_occupancy_done() {
740 status.code = status.UNDEFINED;
741 update();
744 virtual void d3_writing_output(const char *name) {
745 static int section_announced = 0;
747 if (!section_announced) {
748 printf(":\n");
749 section_announced = 1;
752 printf(" '%s'", name);
754 update();
757 virtual void d3_writing_output_done() {
758 status.code = status.UNDEFINED;
759 printf(".\n");
760 update();
764 * Warnings
767 virtual void warn(const char *string) {
768 printf("\n\n*** Warning: %s. ***\n\n\n");
772 * Errors
775 virtual void exec_failure(const char *exec, const char *arg1, const char *arg2) {
776 printf("\n\n*** An error occurred while running `%s %s %s`. ***\n\n\n", exec, arg1, arg2);
777 exit(1);
780 virtual void fork_failure(const char *location) {
781 printf("\n\n*** Could not fork in %s. ***\n\n\n", location);
782 exit(1);
785 virtual void memory_error(const char *purpose) {
786 printf("\n\n*** Unable to allocate memory for %s. ***\n\n\n", purpose);
787 exit(1);
790 virtual void memory_error_location(const char *location) {
791 printf("\n\n*** Unable to allocate memory in %s.\n\n\n", location);
792 exit(1);
795 virtual void cli_not_enough(const char *option) {
796 printf("\n\n*** Not enough arguments for `%s' ***\n\n\n", option);
797 exit(1);
800 virtual void cli_bad_arg(const char *option) {
801 printf("\n\n*** Bad argument to `%s' ***\n\n", option);
802 exit(1);
805 virtual void error(const char *string) {
806 printf("\n\n*** Error: %s. ***\n\n\n", string);
807 exit(1);
810 virtual void illegal_option(const char *string) {
811 printf("\n\n*** Error: illegal option %s ***\n\n", string);
812 exit(1);
815 virtual void unknown_device(const char *string) {
816 printf("\n\n*** Error: unknown device %s ***\n\n", string);
817 exit(1);
820 virtual void error_hint(const char *error, const char *hint) {
821 printf("\n\n*** Error: %s", error);
822 printf( "\n*** Hint: %s\n\n\n", hint);
823 exit(1);
826 virtual void cache(double usage, double max) {
829 virtual void log_message(const char *message) {
832 virtual ~ui() {
836 #include "ui_wo.h"
838 #endif