[GRASS-SVN] r68085 - in grass-addons/grass7/imagery: . i.gcp

svn_grass at osgeo.org svn_grass at osgeo.org
Sun Mar 20 22:57:32 PDT 2016


Author: hcho
Date: 2016-03-20 22:57:32 -0700 (Sun, 20 Mar 2016)
New Revision: 68085

Added:
   grass-addons/grass7/imagery/i.gcp/
   grass-addons/grass7/imagery/i.gcp/Makefile
   grass-addons/grass7/imagery/i.gcp/i.gcp.html
   grass-addons/grass7/imagery/i.gcp/main.c
   grass-addons/grass7/imagery/i.gcp/points.c
Log:
i.gcp: Add a new module for managing Ground Control Points (GCPs) non-interactively

Added: grass-addons/grass7/imagery/i.gcp/Makefile
===================================================================
--- grass-addons/grass7/imagery/i.gcp/Makefile	                        (rev 0)
+++ grass-addons/grass7/imagery/i.gcp/Makefile	2016-03-21 05:57:32 UTC (rev 68085)
@@ -0,0 +1,10 @@
+MODULE_TOPDIR = ../..
+
+PGM = i.gcp
+
+LIBES = $(GISLIB) $(IMAGERYLIB)
+DEPENDENCIES = $(GISDEP) $(IMAGERYDEP)
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd

Added: grass-addons/grass7/imagery/i.gcp/i.gcp.html
===================================================================
--- grass-addons/grass7/imagery/i.gcp/i.gcp.html	                        (rev 0)
+++ grass-addons/grass7/imagery/i.gcp/i.gcp.html	2016-03-21 05:57:32 UTC (rev 68085)
@@ -0,0 +1,94 @@
+<h2>DESCRIPTION</h2>
+
+<em>i.gcp</em> manages Ground Control Points (GCPs) non-interactively.
+
+
+<h2>NOTES</h2>
+
+Unlike <em>g.gui.gcp</em>, <em>i.gcp</em> can be invoked from the command line
+or scripts to manage GCPs. It is recommended to create a backup copy of the
+original POINTS file using <b>-b</b> before making changes to the file. The
+backup POINTS file (POINTS_BAK) can be restored using <b>-r</b> or removed
+later using <b>-B</b>. GCPs in the backup POINTS file can be listed using
+<b>-L</b>.
+
+
+<h2>EXAMPLES</h2>
+
+List all GCPs in group "sar":
+<div class="code"><pre>
+i.gcp -l group=sar
+</pre></div>
+
+Create a backup copy of the current POINTS file:
+<div class="code"><pre>
+i.gcp -b group=sar
+</pre></div>
+
+Clear all GCPs first by removing the POINTS file:
+<div class="code"><pre>
+i.gcp -c group=sar
+</pre></div>
+
+Add new GCPs at the bottom-left and top-right corners of the satellite imagery:
+<div class="code"><pre>
+i.gcp group=sar image_coordinates=0,0,31996,32239 target_coordinates=493920,3880490,529470,3916310
+</pre></div>
+
+Add another GCP that will be ignored for now and list all GCPs:
+<div class="code"><pre>
+i.gcp -l group=sar image_coordinates=100,100 target_coordinates=500000,4000000 status=ignore
+</pre></div>
+
+Use the GCP just added and list all:
+<div class="code"><pre>
+i.gcp -u -l group=sar point=3
+</pre></div>
+
+Delete point 1:
+<div class="code"><pre>
+i.gcp -d -l group=sar point=1
+</pre></div>
+
+Ignore points 1-2:
+<div class="code"><pre>
+i.gcp -i -l group=sar point=1-2
+</pre></div>
+
+List GCPs in the backup POINTS file:
+<div class="code"><pre>
+i.gcp -L group=sar
+</pre></div>
+
+Restore the backup POINTS file:
+<div class="code"><pre>
+i.gcp -r group=sar
+</pre></div>
+
+Remove the backup POINTS file:
+<div class="code"><pre>
+i.gcp -B group=sar
+</pre></div>
+
+
+<h2>SEE ALSO</h2>
+
+The GRASS 4 <em>
+<a href="http://grass.OSGeo.org/gdp/imagery/grass4_image_processing.pdf">Image
+Processing manual</a></em>
+
+<p>
+<em>
+<a href="i.group.html">i.group</a><br>
+<a href="i.target.html">i.target</a><br>
+<a href="i.rectify.html">i.rectify</a><br>
+<a href="wxGUI.GCP_Manager.html">Ground Control Point Manager</a>
+</em>
+
+
+<h2>AUTHOR</h2>
+
+<a href="mailto:grass4u at gmail com">Huidae Cho</a>
+
+<p>
+<i>Last changed: $Date: 2012-04-10 14:52:23 -0400 (Tue, 10 Apr 2012) $</i>

Added: grass-addons/grass7/imagery/i.gcp/main.c
===================================================================
--- grass-addons/grass7/imagery/i.gcp/main.c	                        (rev 0)
+++ grass-addons/grass7/imagery/i.gcp/main.c	2016-03-21 05:57:32 UTC (rev 68085)
@@ -0,0 +1,324 @@
+
+/****************************************************************************
+ *
+ * MODULE:       i.gcp
+ *
+ * AUTHOR(S):    Huidae Cho <grass4u gmail.com>
+ *
+ * PURPOSE:      Manages ground control points non-interactively.
+ *
+ * COPYRIGHT:    (C) 2016 by the GRASS Development Team
+ *
+ *               This program is free software under the GNU General Public
+ *               License (>=v2). Read the file COPYING that comes with GRASS
+ *               for details.
+ *
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <grass/gis.h>
+#include <grass/imagery.h>
+#include <grass/glocale.h>
+
+/* points.c */
+void backup_point_file(const char *);
+void restore_backup_point_file(const char *);
+void list_backup_point_file(const char *);
+void remove_backup_point_file(const char *);
+int find_point_file(const char *);
+void remove_point_file(const char *);
+void create_point_file(const char *);
+void list_points(struct Control_Points *);
+
+int main(int argc, char **argv)
+{
+    struct GModule *module;
+    struct
+    {
+	struct Option *group;
+	struct Option *image_coords;
+	struct Option *target_coords;
+	struct Option *status;
+	struct Option *point;
+    } opt;
+    struct
+    {
+	struct Flag *list;
+	struct Flag *clear;
+	struct Flag *delete;
+	struct Flag *use;
+	struct Flag *ignore;
+	struct Flag *backup;
+	struct Flag *restore;
+	struct Flag *list_backup;
+	struct Flag *remove_backup;
+    } flag;
+    char *group, **image_coords, **target_coords;
+    int status;
+    int i;
+    struct Control_Points cp;
+    int num_deleted;
+
+    G_gisinit(argv[0]);
+
+    module = G_define_module();
+    G_add_keyword(_("imagery"));
+    G_add_keyword(_("georectification"));
+    G_add_keyword(_("GCP"));
+    module->description = _("Manages Ground Control Points (GCPs) non-interactively.");
+
+    opt.group = G_define_standard_option(G_OPT_I_GROUP);
+
+    opt.image_coords = G_define_standard_option(G_OPT_M_COORDS);
+    opt.image_coords->key = "image_coordinates";
+    opt.image_coords->description = _("Image coordinates to add");
+
+    opt.target_coords = G_define_standard_option(G_OPT_M_COORDS);
+    opt.target_coords->key = "target_coordinates";
+    opt.target_coords->description = _("Target coordinates to add");
+
+    opt.status = G_define_option();
+    opt.status->key = "status";
+    opt.status->description = _("Status for new ground control points");
+    opt.status->type = TYPE_STRING;
+    opt.status->options = "use,ignore";
+    opt.status->answer = "use";
+
+    opt.point = G_define_option();
+    opt.point->key = "point";
+    opt.point->description = _("Point number(s) to manage");
+    opt.point->type = TYPE_INTEGER;
+    opt.point->multiple = YES;
+    opt.point->options = "1-";
+
+    flag.list = G_define_flag();
+    flag.list->key = 'l';
+    flag.list->description = _("List all ground control points");
+
+    flag.clear = G_define_flag();
+    flag.clear->key = 'c';
+    flag.clear->description = _("Clear all ground control points");
+
+    flag.delete = G_define_flag();
+    flag.delete->key = 'd';
+    flag.delete->description = _("Delete selected ground control points");
+
+    flag.use = G_define_flag();
+    flag.use->key = 'u';
+    flag.use->description = _("Use selected ground control points");
+
+    flag.ignore = G_define_flag();
+    flag.ignore->key = 'i';
+    flag.ignore->description = _("Ignore selected ground control points");
+
+    flag.backup = G_define_flag();
+    flag.backup->key = 'b';
+    flag.backup->description = _("Back up the point file");
+
+    flag.restore = G_define_flag();
+    flag.restore->key = 'r';
+    flag.restore->description = _("Restore the backup point file");
+
+    flag.list_backup = G_define_flag();
+    flag.list_backup->key = 'L';
+    flag.list_backup->description = _("List all ground control points in the backup point file");
+
+    flag.remove_backup = G_define_flag();
+    flag.remove_backup->key = 'B';
+    flag.remove_backup->description = _("Remove the backup point file");
+
+    /* both image and target coordinates are required collectively */
+    G_option_collective(opt.image_coords, opt.target_coords, NULL);
+    /* one of these flags or options is required, but point= alone is not */
+    G_option_required(flag.list, flag.clear, flag.delete, flag.use, flag.ignore, flag.backup, flag.restore, flag.list_backup, flag.remove_backup, opt.image_coords, NULL);
+    /* however, they are mutually exclusive except flag.list */
+    G_option_exclusive(flag.clear, flag.delete, flag.use, flag.ignore, flag.backup, flag.restore, flag.list_backup, flag.remove_backup, opt.image_coords, NULL);
+    /* don't need to list after clear, backup, or restore */
+    G_option_exclusive(flag.list, flag.clear, flag.backup, flag.restore, flag.list_backup, flag.remove_backup, NULL);
+    /* point= is used to select points to delete, use, or ignore */
+    G_option_requires(flag.delete, opt.point, NULL);
+    G_option_requires(flag.use, opt.point, NULL);
+    G_option_requires(flag.ignore, opt.point, NULL);
+
+    if (G_parser(argc, argv))
+	exit(EXIT_FAILURE);
+
+    group = opt.group->answer;
+    image_coords = opt.image_coords->answers;
+    target_coords = opt.target_coords->answers;
+    status = strcmp(opt.status->answer, "use") == 0;
+
+    /* does group exist? */
+    if (!I_find_group(group))
+	G_fatal_error(_("Specified group does not exist in current mapset"));
+
+    if (flag.backup->answer) {
+	/* back up point file */
+	backup_point_file(group);
+	exit(EXIT_SUCCESS);
+    }
+
+    if (flag.restore->answer) {
+	/* restore backup point file */
+	restore_backup_point_file(group);
+	exit(EXIT_SUCCESS);
+    }
+
+    if (flag.list_backup->answer) {
+	/* list backup point file */
+	list_backup_point_file(group);
+	exit(EXIT_SUCCESS);
+    }
+
+    if (flag.remove_backup->answer) {
+	/* remove backup point file */
+	remove_backup_point_file(group);
+	exit(EXIT_SUCCESS);
+    }
+
+    if (flag.clear->answer) {
+	/* remove control point file */
+	remove_point_file(group);
+	exit(EXIT_SUCCESS);
+    }
+
+    /* read in control points if any */
+    if (find_point_file(group)) {
+	if (!I_get_control_points(group, &cp))
+	    G_fatal_error(_("Failed to read control point file"));
+    } else {
+	cp.count = 0;
+	cp.e1 = NULL;
+	cp.n1 = NULL;
+	cp.e2 = NULL;
+	cp.n2 = NULL;
+	cp.status = NULL;
+    }
+    num_deleted = 0;
+
+    if (flag.delete->answer || flag.use->answer || flag.ignore->answer) {
+	/* delete, use, or ignore existing control points */
+	char *ans;
+	int j, tmp;
+	int *points;
+	int num_points;
+	int new_status;
+
+	if (cp.count == 0)
+	    G_fatal_error(_("There are no control points to manage"));
+
+	/* read control point numbers */
+	for (num_points = 0; opt.point->answers[num_points]; num_points++);
+	points = (int *)G_malloc(num_points * sizeof(int));
+
+	for (i = j = 0; (ans = opt.point->answers[i]); i++) {
+	    char *p;
+
+	    /* if ans is a range */
+	    if ((p = strchr(ans, '-'))) {
+		int lo, hi;
+
+		/* more than one range is not allowed in one answer */
+		if (p != strrchr(ans, '-'))
+		    G_fatal_error(_("%s: Invalid range for point numbers"), ans);
+		/* only lo-hi is allowed, not lo- or -hi */
+		if (sscanf(ans, "%d-%d", &lo, &hi) == 2) {
+		    if (hi < lo) {
+			tmp = hi;
+			hi = lo;
+			lo = tmp;
+		    }
+		} else
+		    G_fatal_error(_("%s: Invalid range for point numbers"), ans);
+
+		if (hi > cp.count)
+		    hi = cp.count;
+
+		num_points += hi - lo;
+		points = (int *)G_realloc(points, num_points * sizeof(int));
+
+		for (; lo <= hi; lo++)
+		    points[j++] = lo;
+	    } else {
+		tmp = atoi(ans);
+		if (tmp > cp.count)
+		    tmp = cp.count;
+
+		points[j++] = tmp;
+	    }
+	}
+
+	/* no points selected */
+	if (num_points == 0)
+	    G_fatal_error(_("No control points selected to manage"));
+
+	if (flag.delete->answer)
+	    /* the imagery library only stores status >= 0 */
+	    new_status = -1;
+	else if (flag.use->answer)
+	    /* status = 1 means use */
+	    new_status = 1;
+	else
+	    /* status = 0 means ignore */
+	    new_status = 0;
+
+	for (i = 0; i < cp.count; i++) {
+	    int j;
+
+	    /* find points */
+	    for (j = 0; j < num_points; j++) {
+		if (points[j] == i + 1) {
+		    /* update status */
+		    cp.status[i] = new_status;
+		    break;
+		}
+	    }
+	}
+
+	if (new_status == -1) {
+	    for (i = 0; i < cp.count; i++) {
+		if (cp.status[i] == -1)
+		    num_deleted++;
+	    }
+	}
+    } else if (image_coords) {
+	/* add new control points */
+	int n;
+
+	/* # of image coords must be the same as # of target coords */
+	for (i = 0; image_coords[i]; i++);
+	n = i;
+
+	for (i = 0; target_coords[i]; i++);
+	if (i != n)
+	    G_fatal_error(_("Image and target coordinates have different numbers of points"));
+
+	/* loop through all image and target coordinates */
+	for (i = 0; i < n; i += 2) {
+	    double e1, n1, e2, n2;
+
+	    e1 = atof(image_coords[i]);
+	    n1 = atof(image_coords[i + 1]);
+	    e2 = atof(target_coords[i]);
+	    n2 = atof(target_coords[i + 1]);
+
+	    /* create a new control point */
+	    I_new_control_point(&cp, e1, n1, e2, n2, status);
+	}
+    }
+
+    /* save control points */
+    if (!I_put_control_points(group, &cp))
+	G_fatal_error(_("Failed to write control point file"));
+
+    if (flag.list->answer) {
+	/* list existing control points */
+	if (cp.count - num_deleted > 0)
+	    list_points(&cp);
+	else
+	    fprintf(stdout, _("No control points found\n"));
+    }
+
+    exit(EXIT_SUCCESS);
+}

Added: grass-addons/grass7/imagery/i.gcp/points.c
===================================================================
--- grass-addons/grass7/imagery/i.gcp/points.c	                        (rev 0)
+++ grass-addons/grass7/imagery/i.gcp/points.c	2016-03-21 05:57:32 UTC (rev 68085)
@@ -0,0 +1,149 @@
+#include <stdio.h>
+#include <grass/gis.h>
+#include <grass/imagery.h>
+#include <grass/glocale.h>
+
+#define POINT_FILE "POINTS"
+#define POINT_BAK_FILE "POINTS_BAK"
+
+void list_points(struct Control_Points *);
+
+/* copied from lib/imagery/points.c */
+static int I_read_control_points(FILE * fd, struct Control_Points *cp)
+{
+    char buf[100];
+    double e1, e2, n1, n2;
+    int status;
+
+    cp->count = 0;
+
+    /* read the control point lines. format is:
+       image_east image_north  target_east target_north  status
+     */
+    cp->e1 = NULL;
+    cp->e2 = NULL;
+    cp->n1 = NULL;
+    cp->n2 = NULL;
+    cp->status = NULL;
+
+    while (G_getl2(buf, sizeof buf, fd)) {
+	G_strip(buf);
+	if (*buf == '#' || *buf == 0)
+	    continue;
+	if (sscanf(buf, "%lf%lf%lf%lf%d", &e1, &n1, &e2, &n2, &status) == 5)
+	    I_new_control_point(cp, e1, n1, e2, n2, status);
+	else
+	    return -4;
+    }
+
+    return 1;
+}
+/**********/
+
+void backup_point_file(const char *group)
+{
+    char path[GPATH_MAX], bak[GPATH_MAX];
+
+    if (!I_find_group_file(group, POINT_FILE))
+	G_fatal_error(_("No control point file exists"));
+
+    if (I_find_group_file(group, POINT_BAK_FILE))
+	G_fatal_error(_("Backup control point file alreay exists"));
+
+    G_file_name_misc(path, "group", POINT_FILE, group, G_mapset());
+    G_file_name_misc(bak, "group", POINT_BAK_FILE, group, G_mapset());
+
+    if (!G_copy_file(path, bak))
+	G_fatal_error(_("Unable to create a backup copy of control point file"));
+}
+
+void restore_backup_point_file(const char *group)
+{
+    char path[GPATH_MAX], bak[GPATH_MAX];
+
+    if (!I_find_group_file(group, POINT_BAK_FILE))
+	G_fatal_error(_("No backup control point file exists"));
+
+    G_file_name_misc(path, "group", POINT_FILE, group, G_mapset());
+    G_file_name_misc(bak, "group", POINT_BAK_FILE, group, G_mapset());
+
+    if (!G_copy_file(bak, path))
+	G_fatal_error(_("Unable to restore backup control point file"));
+}
+
+void list_backup_point_file(const char *group)
+{
+    FILE *fd;
+    int stat;
+    struct Control_Points cp;
+
+    if (!I_find_group_file(group, POINT_BAK_FILE))
+	G_fatal_error(_("No backup control point file exists"));
+
+    fd = I_fopen_group_file_old(group, POINT_BAK_FILE);
+    if (fd == NULL)
+	G_fatal_error(_("Unable to open backup control point file for group [%s in %s]"),
+		  group, G_mapset());
+
+    stat = I_read_control_points(fd, &cp);
+    fclose(fd);
+    if (stat < 0)
+	G_fatal_error(_("Bad format in control point file for group [%s in %s]"),
+		  group, G_mapset());
+
+    list_points(&cp);
+}
+
+void remove_backup_point_file(const char *group)
+{
+    if (!I_find_group_file(group, POINT_BAK_FILE))
+	G_fatal_error(_("No backup control point file exists"));
+
+    if (G_remove_misc("group", POINT_BAK_FILE, group) < 0)
+	G_fatal_error(_("Unable to remove backup control point file"));
+}
+
+int find_point_file(const char *group)
+{
+    return I_find_group_file(group, POINT_FILE);
+}
+
+void remove_point_file(const char *group)
+{
+    if (!I_find_group_file(group, POINT_FILE))
+	return;
+
+    if (G_remove_misc("group", POINT_FILE, group) < 0)
+	G_fatal_error(_("Unable to remove control point file"));
+}
+
+void create_point_file(const char *group)
+{
+    FILE *fd;
+
+    if (I_find_group_file(group, POINT_FILE))
+	G_fatal_error(_("Control point file already exists"));
+
+    fd = I_fopen_group_file_new(group, POINT_FILE);
+    if (fd == NULL)
+        G_fatal_error(_("Unable to create control point file for group [%s in %s]"),
+                  group, G_mapset());
+
+    fclose(fd);
+}
+
+void list_points(struct Control_Points *cp)
+{
+    int i, j;
+
+    fprintf(stdout, "%5s %7s %15s %15s %15s %7s %6s\n",
+	    "point", "", "image", "", "target", "", "status");
+    fprintf(stdout, "%5s %15s %15s %15s %15s\n",
+	    "", "east", "north", "east", "north");
+    for (i = 0, j = 1; i < cp->count; i++) {
+	if (cp->status[i] >= 0)
+	    fprintf(stdout, "%5d %15f %15f %15f %15f %6s\n",
+		    j++, cp->e1[i], cp->n1[i], cp->e2[i], cp->n2[i],
+		    cp->status[i] == 1 ? "use" : "ignore");
+    }
+}



More information about the grass-commit mailing list