#include #include #include #include "globals.h" #include #include "crs.h" #define NLINES 18 struct box { int top, bottom, left,right; }; static int which; static struct box more, less, report; static int height, size, edge, nlines; static int curp, first_point; static double rms; static double *xres, *yres, *gnd; static int pager; static int xmax, ymax, gmax; static char buf[300]; static char delete_msg[11] = "delete_off"; static char pick_msg[40] = " Double click to include/exclude pt. "; static int delete_mode; static char order_msg[10] = "1st ORDER"; static int trans_order = 1; #define FMT0(buf,n) \ sprintf (buf, "%3d ", n) #define FMT1(buf,xres,yres,gnd) \ sprintf (buf, "%5.1f %5.1f %6.1f ", xres,yres,gnd) #define LHEAD1 " error " #define LHEAD2 " # col row target" #define FMT2(buf,e1,n1,e2,n2) \ sprintf (buf, "%9.1f %9.1f %9.1f %9.1f ", e1,n1,e2,n2) #define RHEAD1 " image target" #define RHEAD2 " east north east north" #define BACKGROUND GREY static int delete_mark(void); static int do_warp(void); static int rast_redraw(void); static int warp(void); static int no_warp(void); static int downarrow (struct box *,int); static int uparrow (struct box *,int); static int pick(int,int); static int get_order(void); static int show_point (int,int); static int printcentered (FILE *,char *,int); static int inbox (struct box *,int,int); static int cancel_which(void); static int done(void); static int do_report (FILE *); static int to_printer(void); static int askfile(void); static int to_file(void); static int dotext (char *,int,int,int,int,int,int); static int compute_transformation(void); static int do_1st (void) { strcpy(order_msg,"1st ORDER"); trans_order = 1; if( compute_transformation() ) return 1; /* back to analyze menu */ rast_redraw(); return 1; } static int do_2nd (void) { strcpy(order_msg,"2nd ORDER"); trans_order = 2; if( compute_transformation() ) return 0; rast_redraw(); return 1; } static int do_3rd (void) { strcpy(order_msg,"3rd ORDER"); trans_order = 3; if( compute_transformation() ) return 0; rast_redraw(); return 1; } static int delete_mark (void) { if(delete_mode) { strcpy(pick_msg," Double click to include/exclude point"); strcpy(delete_msg,"delete_off"); delete_mode = 0; } else { strcpy(pick_msg," Double click on point to be DELETED "); strcpy(delete_msg,"DELETE_ON "); delete_mode = 1; } pager = 1; /* redisplay entire form */ return 1; } int delete_control_point (int n) { int i; char msg[80]; if((n < 0) | (n > group.points.count -1)) { sprintf(msg,"%d is an invalid control point index value.",n); G_warning(msg); return 1; } for(i = n; i < group.points.count -1; i++) { G_copy(&group.points.e1[i], &group.points.e1[i+1], sizeof(group.points.e1[0])); G_copy(&group.points.n1[i], &group.points.n1[i+1], sizeof(group.points.n1[0])); G_copy(&group.points.e2[i], &group.points.e2[i+1], sizeof(group.points.e2[0])); G_copy(&group.points.n2[i], &group.points.n2[i+1], sizeof(group.points.n2[0])); G_copy(&group.points.status[i], &group.points.status[i+1], sizeof(group.points.status[0])); } group.points.count -= 1; if(I_put_control_points(group.name,&group.points) < 0) { G_fatal_error("bad return on I_put_control_points"); return 1; } return 0; } /*--------------------------------------------------------------- */ static int do_warp (void) { static int use = 1; int warp(); int no_warp(); int x,y; int rast_redraw(); static Objects objects[] = { MENU("RASTER REDRAW", rast_redraw, &use), INFO("Overlay vectors on raster image? ",&use), MENU("NO", no_warp, &use), MENU("YES", warp, &use), {0} }; x = (SCREEN_LEFT + SCREEN_RIGHT) / 2; y = SCREEN_BOTTOM; Set_mouse_xy(x,y); Input_pointer(objects); return 1; } static int no_warp (void) { return -1; } static int warp (void) { warpvect(group.E21,group.N21,trans_order); return -1; } static int rast_redraw (void) { Erase_view(VIEW_MAP1); drawcell(VIEW_MAP1,0); /* 0 means don't initialize VIEW_MAP2 */ display_points(1); return 0; } static int uparrow (struct box *box,int color) { R_standard_color (color); Uparrow (box->top+edge, box->bottom-edge, box->left+edge, box->right-edge); return 0; } static int downarrow (struct box *box,int color) { R_standard_color (color); Downarrow (box->top+edge, box->bottom-edge, box->left+edge, box->right-edge); return 0; } static int pick(int x,int y) { int n; int cur; cur = which; cancel_which(); if (inbox(&more,x,y)) { if (curp >= group.points.count) return 0; first_point = curp; pager = 1; return 1; } if (inbox(&less,x,y)) { if (first_point == 0) return 0; first_point -= nlines; if (first_point < 0) first_point = 0; pager = 1; return 1; } if (!inbox (&report,x,y)) { return 0; } n = (y - report.top)/height; if (n == cur) /* second click! */ { if(!delete_mode) { group.points.status[first_point+n] = !group.points.status[first_point+n]; compute_transformation(); show_point (first_point+n, 1); return 1; } else { delete_control_point(first_point+n); first_point = 0; compute_transformation(); pager = 1; return 1; } } /* first click */ which = n; show_point (first_point+n, 0); if(!delete_mode) R_standard_color (RED); else R_standard_color(ORANGE); Outline_box ((report.top + n*height)+1, report.top +(n+1)*height, report.left, report.right-1); R_flush(); return 0; /* ignore first click */ } static int done (void) { cancel_which(); return -1; } static int cancel_which (void) { if (which >= 0) { R_standard_color (BACKGROUND); Outline_box ((report.top + which*height)+1, report.top +(which+1)*height, report.left, report.right-1); show_point (first_point+which, 1); } which = -1; return 0; } static int inbox (struct box *box,int x,int y) { return (x>box->left && x right && y>box->top && ybottom); } static int dotext ( char *text,int top,int bottom,int left,int right,int centered,int color) { R_standard_color (BACKGROUND); R_box_abs (left, top, right, bottom); R_standard_color (color); R_move_abs (left+1+edge, bottom-1-edge); if (centered) R_move_rel ((right-left-strlen(text)*size)/2,0); R_set_window (top, bottom, left, right); /* for text clipping */ R_text (text); R_set_window (SCREEN_TOP, SCREEN_BOTTOM, SCREEN_LEFT, SCREEN_RIGHT); return 0; } static int compute_transformation (void) { /* returns 0 on success, 1 on fail */ int n, count; double d,d1,d2,sum; double e1, e2, n1, n2; double xval, yval, gval; double sqrt(); static int order_pnts[3] = { 3, 6, 10}; char msg[40]; xmax = ymax = gmax = 0; xval = yval = gval = 0.0; CRS_Compute_equation(trans_order); if (group.equation_stat <= 0) { if(group.equation_stat == 0) { sprintf(msg,"Not Enough Points -- %d are required.",order_pnts[trans_order-1]); Menu_msg(msg); G_sleep(2); } return 1; } /* compute the row,col error plus ground error * keep track of largest and second largest error */ sum = 0.0; rms = 0.0; count = 0; for (n = 0; n < group.points.count; n++) { if (group.points.status[n] <= 0) continue; count++; CRS_georef (group.points.e2[n], group.points.n2[n], &e1, &n1, group.E21, group.N21,trans_order); CRS_georef (group.points.e1[n], group.points.n1[n], &e2, &n2, group.E12, group.N12,trans_order); if((d = xres[n] = e1-group.points.e1[n]) < 0) d = -d; if (d > xval) { xmax = n; xval = d; } if ((d = yres[n] = n1-group.points.n1[n]) < 0) d = -d; if (d > yval) { ymax = n; yval = d; } /* compute ground error (ie along diagonal) */ d1 = e2 - group.points.e2[n]; d2 = n2 - group.points.n2[n]; d = d1*d1 + d2*d2; sum += d; /* add it to rms sum, before taking sqrt */ d = sqrt(d); gnd[n] = d; if (d > gval) /* is this one the max? */ { gmax = n; gval = d; } } /* compute overall rms error */ if (count) rms = sqrt (sum/count); return 0; } static int to_file (void) { FILE *fd; char msg[1024]; cancel_which(); if (Input_other (askfile, "Keyboard") < 0) { return 0; } fd = fopen (buf, "w"); if (fd == NULL) { sprintf (msg, "** Unable to create file %s\n", buf); Beep(); Curses_write_window (PROMPT_WINDOW, 2, 1, msg); } else { do_report (fd); fclose (fd); sprintf (msg, "Report saved in file %s\n", buf); Curses_write_window (PROMPT_WINDOW, 2, 1, msg); } return 0; } static int askfile (void) { char file[GNAME_MAX]; while (1) { Curses_prompt_gets ("Enter file to hold report: ", file); G_strip (file); if (*file == 0) return -1; if (G_index (file, '/')) strcpy (buf, file); else sprintf (buf, "%s/%s", G_home(), file); if (access (buf, 0) != 0) return 1; sprintf (buf, "** %s already exists. choose another file", file); Beep(); Curses_write_window (PROMPT_WINDOW, 2, 1, buf); } return 0; } static int to_printer (void) { FILE *fd; cancel_which(); Menu_msg ("Sending report to printer ..."); Curses_write_window(PROMPT_WINDOW, 1, 1, "Sending report to printer ..."); fd = popen ("lp", "w"); do_report (fd); pclose (fd); return 0; } static int do_report (FILE *fd) { char buf[100]; int n; int width; fprintf (fd, "LOCATION: %-20s GROUP: %-20s MAPSET: %s\n\n", G_location(), group.name, G_mapset()); fprintf (fd, "%15sAnalysis of control point registration\n\n", ""); fprintf (fd, "%s %s\n", LHEAD1, RHEAD1); fprintf (fd, "%s %s\n", LHEAD2, RHEAD2); FMT1 (buf,0.0,0.0,0.0); width = strlen (buf); for (n = 0; n < group.points.count; n++) { FMT0(buf,n+1); fprintf (fd, "%s", buf); if(group.equation_stat > 0 && group.points.status[n] > 0) { FMT1(buf, xres[n], yres[n], gnd[n]); fprintf (fd, "%s", buf); } else if (group.points.status[n] > 0) printcentered (fd, "?", width); else printcentered (fd, "not used", width); FMT2(buf, group.points.e1[n], group.points.n1[n], group.points.e2[n], group.points.n2[n]); fprintf (fd, " %s\n", buf); } fprintf (fd, "\n"); if (group.equation_stat < 0) fprintf (fd, "Poorly place control points\n"); else if (group.equation_stat == 0) fprintf (fd, "No active control points\n"); else fprintf (fd, "Overall rms error: %.2f %s Transformation\n", rms,order_msg); return 0; } static int printcentered (FILE *fd,char *buf,int width) { int len; int n; int i; len = strlen (buf); n = (width -len)/2; for (i = 0; i < n; i++) fprintf (fd, " "); fprintf (fd, "%s", buf); i += len; while (i++ < width) fprintf (fd, " "); return 0; } static int show_point (int n,int true_color) { if (!true_color) R_standard_color (ORANGE); else if(group.points.status[n]) R_standard_color (GREEN); else R_standard_color (RED); display_one_point (VIEW_MAP1, group.points.e1[n], group.points.n1[n]); return 0; } static int get_order (void) { static int use = 1; static Objects objects[]= { INFO("Select order of transformation->", &use), MENU("1st Order", do_1st, &use), MENU("2nd Order", do_2nd, &use), MENU("3rd Order", do_3rd, &use), {0} }; if(Input_pointer(objects) < 0) return -1; return 1; } int analyze (void) { static int use = 1; static Objects objects[]= { MENU("DONE", done, &use), MENU("PRINT", to_printer, &use), MENU("FILE", to_file, &use), MENU("OVERLAY", do_warp, &use), MENU(delete_msg, delete_mark, &use), INFO("Transform->", &use), MENU(order_msg, get_order, &use), INFO(pick_msg, &use), OTHER(pick,&use), {0} }; int color; int tsize; int cury; int len; int line; int top, bottom, left, right, width, middle, nums; /* to give user a response of some sort */ Menu_msg ("Preparing analysis ..."); /* * build a popup window at center of the screen. * 35% the height and wide enough to hold the report * */ /* height of 1 line, based on NLINES taking up 35% vertical space */ height = (.35 * (SCREEN_BOTTOM - SCREEN_TOP))/NLINES + 1; /* size of text, 80% of line height */ tsize = .8 * height; size = tsize-2; /* fudge for computing pixels width of text */ /* indent for the text */ edge = .1 * height + 1; /* determine the length, in chars, of printed line */ FMT0 (buf,0); nums = strlen(buf) * size; FMT1 (buf, 0.0, 0.0, 0.0); len = strlen(buf); middle = len * size; FMT2 (buf, 0.0, 0.0, 0.0, 0.0); len += strlen(buf) ; /* width is for max chars plus sidecar for more/less */ width = len * size + nums + 2*height; if ((SCREEN_RIGHT - SCREEN_LEFT) < width) width = SCREEN_RIGHT - SCREEN_LEFT; /* define the window */ bottom = VIEW_MENU->top-1; top = bottom - height*NLINES; left = SCREEN_LEFT; right = left + width; middle += left + nums; nums += left; /* save what is under this area, so it can be restored */ R_panel_save (tempfile1, top, bottom+1, left, right+1); /* fill it with white */ R_standard_color (BACKGROUND); R_box_abs (left, top, right, bottom); right -= 2*height; /* reduce it to exclude sidecar */ /* print messages in message area */ R_text_size (tsize, tsize); /* setup the more/less boxes in the sidecar */ R_standard_color (BLACK); less.top = top; less.bottom = top + 2*height; less.left = right; less.right = right + 2*height; Outline_box (less.top, less.bottom, less.left, less.right); more.top = bottom - 2*height; more.bottom = bottom; more.left = right; more.right = right + 2*height; Outline_box (more.top, more.bottom, more.left, more.right); /* * top two lines are for column labels * last two line is for overall rms error. */ nlines = NLINES - 3; first_point = 0; /* allocate predicted values */ xres = (double *) G_calloc (group.points.count, sizeof (double)); yres = (double *) G_calloc (group.points.count, sizeof (double)); gnd = (double *) G_calloc (group.points.count, sizeof (double)); /* compute transformation for the first time */ compute_transformation(); /* put head on the report */ cury = top; dotext (LHEAD1, cury, cury+height, left, middle, 0, BLACK); dotext (RHEAD1, cury, cury+height, middle, right-1, 0, BLACK); cury += height; dotext (LHEAD2, cury, cury+height, left, middle, 0, BLACK); dotext (RHEAD2, cury, cury+height, middle, right-1, 0, BLACK); cury += height; R_move_abs (left, cury-1); R_cont_abs (right, cury-1); /* isolate the sidecar */ R_move_abs (right, top); R_cont_abs (right, bottom); /* define report box */ report.top = cury; report.left = left; report.right = right; /* lets do it */ pager = 1; while(1) { R_text_size (tsize, tsize); line = 0; curp = first_point; cury = top + 2*height; while(1) { if (line >= nlines || curp >= group.points.count) break; line++; if(!delete_mode) color = BLACK; else color = BLUE; if(group.equation_stat > 0 && group.points.status[curp] > 0) { /* color = BLACK; */ FMT1(buf, xres[curp], yres[curp], gnd[curp]); if (curp == xmax || curp == ymax || curp == gmax) color = RED; dotext (buf, cury, cury+height, nums, middle, 0, color); } else if (group.points.status[curp] > 0) dotext ("?", cury, cury+height, nums, middle, 1, color); else dotext ("not used", cury, cury+height, nums, middle, 1, color); if (pager) { FMT0 (buf, curp+1); dotext (buf, cury, cury+height, left, nums, 0, color); FMT2(buf, group.points.e1[curp], group.points.n1[curp], group.points.e2[curp], group.points.n2[curp]); dotext (buf, cury, cury+height, middle, right-1, 0, color); } cury += height; curp++; } report.bottom = cury; downarrow (&more, curp < group.points.count ? color : BACKGROUND); uparrow (&less, first_point > 0 ? color : BACKGROUND); R_standard_color (BACKGROUND); R_box_abs (left, cury, right-1, bottom); if (group.equation_stat < 0) { if(group.equation_stat == -1) { color = RED; strcpy (buf, "Poorly placed control points"); } else { if(group.equation_stat == -2) G_fatal_error("NOT ENOUGH MEMORY"); else G_fatal_error("PARAMETER ERROR"); } } else if (group.equation_stat == 0) { color = RED; strcpy (buf, "No active control points"); } else { color = BLACK; sprintf (buf, "Overall rms error: %.2f", rms); } dotext (buf, bottom-height, bottom, left, right-1, 0, color); R_standard_color (BLACK); R_move_abs (left, bottom-height); R_cont_abs (right-1, bottom-height); pager = 0; which = -1; if(Input_pointer(objects) < 0) break; display_points(1); } /* all done. restore what was under the window */ right += 2*height; /* move it back over the sidecar */ R_standard_color (BACKGROUND); R_box_abs (left, top, right, bottom); R_panel_restore (tempfile1); R_panel_delete (tempfile1); R_flush(); G_free (xres); G_free (yres); G_free (gnd); I_put_control_points (group.name, &group.points); display_points(1); return 0; /* return but don't QUIT */ }