6
#include <grass/raster.h>
12
int top, bottom, left, right;
16
static struct box more, less, report;
17
static int height, size, edge, nlines;
18
static int curp, first_point;
20
static double *xres, *yres, *gnd;
22
static int xmax, ymax, gmax;
25
static char delete_msg[11] = "delete_off";
26
static char pick_msg[40] = " Double click to include/exclude pt. ";
27
static int delete_mode;
28
static char order_msg[10] = "1st ORDER";
29
static int trans_order = 1;
32
sprintf (buf, "%3d ", n)
33
#define FMT1(buf,xres,yres,gnd) \
34
sprintf (buf, "%5.1f %5.1f %6.1f ", xres,yres,gnd)
35
#define LHEAD1 " error "
36
#define LHEAD2 " # col row target"
38
#define FMT2(buf,e1,n1,e2,n2) \
39
sprintf (buf, "%9.1f %9.1f %9.1f %9.1f ", e1,n1,e2,n2)
40
#define RHEAD1 " image target"
41
#define RHEAD2 " east north east north"
43
#define BACKGROUND GREY
45
static int delete_mark(void);
46
static int do_warp(void);
47
static int rast_redraw(void);
48
static int warp(void);
49
static int no_warp(void);
50
static int downarrow(struct box *, int);
51
static int uparrow(struct box *, int);
52
static int pick(int, int);
53
static int get_order(void);
54
static int show_point(int, int);
55
static int printcentered(FILE *, char *, int);
56
static int inbox(struct box *, int, int);
57
static int cancel_which(void);
58
static int done(void);
59
static int do_report(FILE *);
60
static int to_printer(void);
61
static int askfile(void);
62
static int to_file(void);
63
static int dotext(char *, int, int, int, int, int, int);
64
static int compute_transformation(void);
66
static int do_1st(void)
68
strcpy(order_msg, "1st ORDER");
70
if (compute_transformation())
71
return 1; /* back to analyze menu */
77
static int do_2nd(void)
79
strcpy(order_msg, "2nd ORDER");
81
if (compute_transformation())
88
static int do_3rd(void)
90
strcpy(order_msg, "3rd ORDER");
92
if (compute_transformation())
99
static int delete_mark(void)
102
strcpy(pick_msg, " Double click to include/exclude point");
103
strcpy(delete_msg, "delete_off");
107
strcpy(pick_msg, " Double click on point to be DELETED ");
108
strcpy(delete_msg, "DELETE_ON ");
111
pager = 1; /* redisplay entire form */
116
int delete_control_point(int n)
121
if ((n < 0) | (n > group.points.count - 1)) {
122
sprintf(msg, "%d is an invalid control point index value.", n);
126
for (i = n; i < group.points.count - 1; i++) {
127
G_copy(&group.points.e1[i], &group.points.e1[i + 1],
128
sizeof(group.points.e1[0]));
129
G_copy(&group.points.n1[i], &group.points.n1[i + 1],
130
sizeof(group.points.n1[0]));
131
G_copy(&group.points.e2[i], &group.points.e2[i + 1],
132
sizeof(group.points.e2[0]));
133
G_copy(&group.points.n2[i], &group.points.n2[i + 1],
134
sizeof(group.points.n2[0]));
135
G_copy(&group.points.status[i], &group.points.status[i + 1],
136
sizeof(group.points.status[0]));
138
group.points.count -= 1;
139
if (I_put_control_points(group.name, &group.points) < 0) {
140
G_fatal_error("bad return on I_put_control_points");
146
/*---------------------------------------------------------------
148
static int do_warp(void)
153
static Objects objects[] = {
154
MENU("RASTER REDRAW", rast_redraw, &use),
155
INFO("Overlay vectors on raster image? ", &use),
156
MENU("NO", no_warp, &use),
157
MENU("YES", warp, &use),
160
x = (SCREEN_LEFT + SCREEN_RIGHT) / 2;
163
Input_pointer(objects);
167
static int no_warp(void)
172
static int warp(void)
174
warpvect(group.E21, group.N21, trans_order);
178
static int rast_redraw(void)
180
Erase_view(VIEW_MAP1);
181
drawcell(VIEW_MAP1, 0); /* 0 means don't initialize VIEW_MAP2 */
187
static int uparrow(struct box *box, int color)
189
R_standard_color(color);
190
Uparrow(box->top + edge, box->bottom - edge, box->left + edge,
196
static int downarrow(struct box *box, int color)
198
R_standard_color(color);
199
Downarrow(box->top + edge, box->bottom - edge, box->left + edge,
205
static int pick(int x, int y)
212
if (inbox(&more, x, y)) {
213
if (curp >= group.points.count)
219
if (inbox(&less, x, y)) {
220
if (first_point == 0)
222
first_point -= nlines;
228
if (!inbox(&report, x, y)) {
232
n = (y - report.top) / height;
233
if (n == cur) { /* second click! */
235
group.points.status[first_point + n] =
236
!group.points.status[first_point + n];
237
compute_transformation();
238
show_point(first_point + n, 1);
242
delete_control_point(first_point + n);
244
compute_transformation();
252
show_point(first_point + n, 0);
254
R_standard_color(RED);
256
R_standard_color(ORANGE);
258
Outline_box((report.top + n * height) + 1, report.top + (n + 1) * height,
259
report.left, report.right - 1);
263
return 0; /* ignore first click */
267
static int done(void)
273
static int cancel_which(void)
276
R_standard_color(BACKGROUND);
277
Outline_box((report.top + which * height) + 1,
278
report.top + (which + 1) * height, report.left,
280
show_point(first_point + which, 1);
287
static int inbox(struct box *box, int x, int y)
289
return (x > box->left && x < box->right && y > box->top &&
293
static int dotext(char *text, int top, int bottom, int left, int right,
294
int centered, int color)
296
R_standard_color(BACKGROUND);
297
R_box_abs(left, top, right, bottom);
298
R_standard_color(color);
299
R_move_abs(left + 1 + edge, bottom - 1 - edge);
301
R_move_rel((right - left - strlen(text) * size) / 2, 0);
302
R_set_window(top, bottom, left, right); /* for text clipping */
304
R_set_window(SCREEN_TOP, SCREEN_BOTTOM, SCREEN_LEFT, SCREEN_RIGHT);
309
static int compute_transformation(void)
310
{ /* returns 0 on success, 1 on fail */
312
double d, d1, d2, sum;
313
double e1, e2, n1, n2;
314
double xval, yval, gval;
315
static int order_pnts[3] = { 3, 6, 10 };
318
xmax = ymax = gmax = 0;
319
xval = yval = gval = 0.0;
321
CRS_Compute_equation(trans_order);
322
if (group.equation_stat <= 0) {
323
if (group.equation_stat == 0) {
324
sprintf(msg, "Not Enough Points -- %d are required.",
325
order_pnts[trans_order - 1]);
333
/* compute the row,col error plus ground error
334
* keep track of largest and second largest error
339
for (n = 0; n < group.points.count; n++) {
340
if (group.points.status[n] <= 0)
343
CRS_georef(group.points.e2[n], group.points.n2[n], &e1, &n1,
344
group.E21, group.N21, trans_order);
345
CRS_georef(group.points.e1[n], group.points.n1[n], &e2, &n2,
346
group.E12, group.N12, trans_order);
348
if ((d = xres[n] = e1 - group.points.e1[n]) < 0)
355
if ((d = yres[n] = n1 - group.points.n1[n]) < 0)
362
/* compute ground error (ie along diagonal) */
363
d1 = e2 - group.points.e2[n];
364
d2 = n2 - group.points.n2[n];
365
d = d1 * d1 + d2 * d2;
366
sum += d; /* add it to rms sum, before taking sqrt */
369
if (d > gval) { /* is this one the max? */
375
/* compute overall rms error */
377
rms = sqrt(sum / count);
382
static int to_file(void)
388
if (Input_other(askfile, "Keyboard") < 0) {
392
fd = fopen(buf, "w");
394
sprintf(msg, "** Unable to create file %s\n", buf);
396
Curses_write_window(PROMPT_WINDOW, 2, 1, msg);
401
sprintf(msg, "Report saved in file %s\n", buf);
402
Curses_write_window(PROMPT_WINDOW, 2, 1, msg);
407
static int askfile(void)
409
char file[GNAME_MAX];
412
Curses_prompt_gets("Enter file to hold report: ", file);
416
if (G_index(file, '/'))
419
sprintf(buf, "%s/%s", G_home(), file);
420
if (access(buf, 0) != 0)
422
sprintf(buf, "** %s already exists. choose another file", file);
424
Curses_write_window(PROMPT_WINDOW, 2, 1, buf);
430
static int to_printer(void)
435
Menu_msg("Sending report to printer ...");
436
Curses_write_window(PROMPT_WINDOW, 1, 1, "Sending report to printer ...");
437
fd = popen("lp", "w");
443
static int do_report(FILE * fd)
449
fprintf(fd, "LOCATION: %-20s GROUP: %-20s MAPSET: %s\n\n",
450
G_location(), group.name, G_mapset());
451
fprintf(fd, "%15sAnalysis of control point registration\n\n", "");
452
fprintf(fd, "%s %s\n", LHEAD1, RHEAD1);
453
fprintf(fd, "%s %s\n", LHEAD2, RHEAD2);
455
FMT1(buf, 0.0, 0.0, 0.0);
458
for (n = 0; n < group.points.count; n++) {
460
fprintf(fd, "%s", buf);
461
if (group.equation_stat > 0 && group.points.status[n] > 0) {
462
FMT1(buf, xres[n], yres[n], gnd[n]);
463
fprintf(fd, "%s", buf);
465
else if (group.points.status[n] > 0)
466
printcentered(fd, "?", width);
468
printcentered(fd, "not used", width);
471
group.points.n1[n], group.points.e2[n], group.points.n2[n]);
472
fprintf(fd, " %s\n", buf);
475
if (group.equation_stat < 0)
476
fprintf(fd, "Poorly place control points\n");
477
else if (group.equation_stat == 0)
478
fprintf(fd, "No active control points\n");
481
"Overall rms error: %.2f %s Transformation\n",
487
static int printcentered(FILE * fd, char *buf, int width)
494
n = (width - len) / 2;
496
for (i = 0; i < n; i++)
498
fprintf(fd, "%s", buf);
506
static int show_point(int n, int true_color)
509
R_standard_color(ORANGE);
510
else if (group.points.status[n])
511
R_standard_color(GREEN);
513
R_standard_color(RED);
515
display_one_point(VIEW_MAP1, group.points.e1[n], group.points.n1[n]);
520
static int get_order(void)
524
static Objects objects[] = {
525
INFO("Select order of transformation->", &use),
526
MENU("1st Order", do_1st, &use),
527
MENU("2nd Order", do_2nd, &use),
528
MENU("3rd Order", do_3rd, &use),
532
if (Input_pointer(objects) < 0)
543
static Objects objects[] = {
544
MENU("DONE", done, &use),
545
MENU("PRINT", to_printer, &use),
546
MENU("FILE", to_file, &use),
547
MENU("OVERLAY", do_warp, &use),
548
MENU(delete_msg, delete_mark, &use),
549
INFO("Transform->", &use),
550
MENU(order_msg, get_order, &use),
551
INFO(pick_msg, &use),
561
int top, bottom, left, right, width, middle, nums;
563
/* to give user a response of some sort */
564
Menu_msg("Preparing analysis ...");
567
* build a popup window at center of the screen.
568
* 35% the height and wide enough to hold the report
572
/* height of 1 line, based on NLINES taking up 35% vertical space */
573
height = (.35 * (SCREEN_BOTTOM - SCREEN_TOP)) / NLINES + 1;
575
/* size of text, 80% of line height */
577
size = tsize - 2; /* fudge for computing pixels width of text */
579
/* indent for the text */
580
edge = .1 * height + 1;
582
/* determine the length, in chars, of printed line */
584
nums = strlen(buf) * size;
585
FMT1(buf, 0.0, 0.0, 0.0);
588
FMT2(buf, 0.0, 0.0, 0.0, 0.0);
591
/* width is for max chars plus sidecar for more/less */
592
width = len * size + nums + 2 * height;
593
if ((SCREEN_RIGHT - SCREEN_LEFT) < width)
594
width = SCREEN_RIGHT - SCREEN_LEFT;
597
/* define the window */
598
bottom = VIEW_MENU->top - 1;
599
top = bottom - height * NLINES;
603
right = left + width;
604
middle += left + nums;
607
/* save what is under this area, so it can be restored */
608
R_panel_save(tempfile1, top, bottom + 1, left, right + 1);
611
/* fill it with white */
612
R_standard_color(BACKGROUND);
613
R_box_abs(left, top, right, bottom);
615
right -= 2 * height; /* reduce it to exclude sidecar */
617
/* print messages in message area */
618
R_text_size(tsize, tsize);
621
/* setup the more/less boxes in the sidecar */
622
R_standard_color(BLACK);
624
less.bottom = top + 2 * height;
626
less.right = right + 2 * height;
627
Outline_box(less.top, less.bottom, less.left, less.right);
629
more.top = bottom - 2 * height;
630
more.bottom = bottom;
632
more.right = right + 2 * height;
633
Outline_box(more.top, more.bottom, more.left, more.right);
636
* top two lines are for column labels
637
* last two line is for overall rms error.
642
/* allocate predicted values */
643
xres = (double *)G_calloc(group.points.count, sizeof(double));
644
yres = (double *)G_calloc(group.points.count, sizeof(double));
645
gnd = (double *)G_calloc(group.points.count, sizeof(double));
647
/* compute transformation for the first time */
648
compute_transformation();
650
/* put head on the report */
652
dotext(LHEAD1, cury, cury + height, left, middle, 0, BLACK);
653
dotext(RHEAD1, cury, cury + height, middle, right - 1, 0, BLACK);
655
dotext(LHEAD2, cury, cury + height, left, middle, 0, BLACK);
656
dotext(RHEAD2, cury, cury + height, middle, right - 1, 0, BLACK);
658
R_move_abs(left, cury - 1);
659
R_cont_abs(right, cury - 1);
661
/* isolate the sidecar */
662
R_move_abs(right, top);
663
R_cont_abs(right, bottom);
665
/* define report box */
668
report.right = right;
674
R_text_size(tsize, tsize);
677
cury = top + 2 * height;
679
if (line >= nlines || curp >= group.points.count)
688
if (group.equation_stat > 0 && group.points.status[curp] > 0) {
690
FMT1(buf, xres[curp], yres[curp], gnd[curp]);
691
if (curp == xmax || curp == ymax || curp == gmax)
693
dotext(buf, cury, cury + height, nums, middle, 0, color);
695
else if (group.points.status[curp] > 0)
696
dotext("?", cury, cury + height, nums, middle, 1, color);
698
dotext("not used", cury, cury + height, nums, middle, 1,
703
dotext(buf, cury, cury + height, left, nums, 0, color);
705
group.points.e1[curp],
706
group.points.n1[curp],
707
group.points.e2[curp], group.points.n2[curp]);
708
dotext(buf, cury, cury + height, middle, right - 1, 0, color);
713
report.bottom = cury;
714
downarrow(&more, curp < group.points.count ? color : BACKGROUND);
715
uparrow(&less, first_point > 0 ? color : BACKGROUND);
716
R_standard_color(BACKGROUND);
717
R_box_abs(left, cury, right - 1, bottom);
718
if (group.equation_stat < 0) {
720
if (group.equation_stat == -1) {
722
strcpy(buf, "Poorly placed control points");
725
if (group.equation_stat == -2)
726
G_fatal_error("NOT ENOUGH MEMORY");
728
G_fatal_error("PARAMETER ERROR");
732
else if (group.equation_stat == 0) {
734
strcpy(buf, "No active control points");
738
sprintf(buf, "Overall rms error: %.2f", rms);
740
dotext(buf, bottom - height, bottom, left, right - 1, 0, color);
741
R_standard_color(BLACK);
742
R_move_abs(left, bottom - height);
743
R_cont_abs(right - 1, bottom - height);
747
if (Input_pointer(objects) < 0)
752
/* all done. restore what was under the window */
753
right += 2 * height; /* move it back over the sidecar */
754
R_standard_color(BACKGROUND);
755
R_box_abs(left, top, right, bottom);
756
R_panel_restore(tempfile1);
757
R_panel_delete(tempfile1);
763
I_put_control_points(group.name, &group.points);
765
return 0; /* return but don't QUIT */