123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- /* ====================================================================
- * PROGRAM: m.cogo
- * AUTHOR: Eric G. Miller <egm2@jps.net>
- * DATE: September 29, 2001
- * PURPOSE: Translates simple COordinate GeOmetry with a format of
- * "[label] <bearing> <distance>" to "X Y [label]".
- *
- * Example: "P0001 S 88-44-56 W 6.7195"
- * "-6.7178980970 -0.1467153972 P0001"
- *
- * The input formats are very limited.
- * --------------------------------------------------------------------
- * COPYRIGHT: (C) 2000 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 <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #include <string.h>
- #include <grass/gis.h>
- #include <grass/glocale.h>
- #define DEG2RAD(a) ((a) * M_PI / 180.0)
- #define RAD2DEG(a) ((a) * 180.0 / M_PI)
- #define DMS2DD(d,m,s) ((d) + ((m) / 60.0) + ((s) / 3600.0))
- #define FORMAT_1 " %s %1[NS] %d%c%d%c%lf %1[EW] %lf "
- #define FORMAT_2 " %1[NS] %d%c%d%c%lf %1[EW] %lf "
- #define FORMAT_3 " %lf %lf %s "
- struct survey_record
- {
- char label[20];
- int haslabel;
- char n_s[2];
- char e_w[2];
- int deg;
- int min;
- double sec;
- double dist;
- double rads;
- double dd;
- double x;
- double y;
- };
- static void print_coordinates(FILE *outfile, struct survey_record *in)
- {
- if (in->haslabel == YES)
- fprintf(outfile, "%.15g %.15g %s\n", in->x, in->y, in->label);
- else
- fprintf(outfile, "%.15g %.15g\n", in->x, in->y);
- }
- static void print_cogo(FILE *outfile, struct survey_record *in)
- {
- if (in->haslabel == YES)
- fprintf(outfile, "%s %s %02d:%02d:%02.9g %s %.13g\n",
- in->label, in->n_s, in->deg, in->min, in->sec,
- in->e_w, in->dist);
- else
- fprintf(outfile, "%s %02d:%02d:%02.9g %s %.13g\n",
- in->n_s, in->deg, in->min, in->sec, in->e_w, in->dist);
- }
- static const char *next_line(FILE *infile)
- {
- static char line[512];
- const char *cptr;
- memset(line, 0, sizeof(line));
- /* TODO: update to G_getl2(), but this fn needs to return pointer to string not ok/EOF int */
- cptr = fgets(line, 512, infile);
- return cptr;
- }
- static int parse_forward(const char *in, struct survey_record *out)
- {
- char dummy1;
- int status;
- if (out->haslabel == YES) {
- status =
- sscanf(in, FORMAT_1, out->label, out->n_s, &out->deg, &dummy1,
- &out->min, &dummy1, &out->sec, out->e_w, &out->dist);
- }
- else {
- status = sscanf(in, FORMAT_2, out->n_s, &out->deg, &dummy1,
- &out->min, &dummy1, &out->sec, out->e_w, &out->dist);
- }
- if ((status != 9 && out->haslabel == YES) ||
- (status != 8 && out->haslabel == NO))
- return 0;
- out->dd = DMS2DD(out->deg, out->min, out->sec);
- if (out->n_s[0] == 'N') {
- if (out->e_w[0] == 'E') {
- out->dd = 90.0 - out->dd;
- }
- else if (out->e_w[0] == 'W') {
- out->dd = 90.0 + out->dd;
- }
- else {
- return 0;
- }
- }
- else if (out->n_s[0] == 'S') {
- if (out->e_w[0] == 'E') {
- out->dd = 270 + out->dd;
- }
- else if (out->e_w[0] == 'W') {
- out->dd = 270 - out->dd;
- }
- else {
- return 0;
- }
- }
- else {
- return 0;
- }
- out->rads = DEG2RAD(out->dd);
- out->x += out->dist * cos(out->rads);
- out->y += out->dist * sin(out->rads);
- return status;
- }
- static int parse_reverse(const char *in, struct survey_record *out)
- {
- double x, y;
- int status;
- status = sscanf(in, FORMAT_3, &x, &y, out->label);
- if (status < 2)
- return 0;
- else if (status == 2)
- out->haslabel = NO;
- else
- out->haslabel = YES;
- G_debug(5, "IN: x=%f y=%f out->x=%f out->y=%f", x, y, out->x, out->y);
- out->rads = atan2(y - out->y, x - out->x);
- out->dist = hypot(x - out->x, y - out->y);
- out->x = x;
- out->y = y;
- out->dd = RAD2DEG(out->rads);
- G_debug(5, "OUT: out->dd=%f out->dist=%f", out->dd, out->dist);
- if (out->rads >= 0.0) {
- out->n_s[0] = 'N';
- out->n_s[1] = '\0';
- }
- else {
- out->n_s[0] = 'S';
- out->n_s[1] = '\0';
- }
- if (fabs(out->rads) >= M_PI_2) {
- out->e_w[0] = 'W';
- out->e_w[1] = '\0';
- }
- else {
- out->e_w[0] = 'E';
- out->e_w[1] = '\0';
- }
- if (out->n_s[0] == 'N') {
- if (out->e_w[0] == 'W') {
- out->dd = out->dd - 90.0;
- }
- else {
- out->dd = 90.0 - out->dd;
- }
- }
- else {
- if (out->e_w[0] == 'W') {
- out->dd = fabs(out->dd) - 90.0;
- }
- else {
- out->dd = 90.0 - fabs(out->dd);
- }
- }
- out->deg = (int)(out->dd);
- out->min = (int)((out->dd - out->deg) * 60.0);
- out->sec = (out->dd - out->deg - out->min / 60.0) * 3600.0;
- return status;
- }
- int main(int argc, char **argv)
- {
- struct Option *input;
- struct Option *output;
- struct Option *coords;
- struct Flag *format;
- struct Flag *reverse;
- struct Flag *close;
- struct GModule *module;
- FILE *infile, *outfile;
- struct survey_record record, first_record;
- const char *cptr;
- char *ss;
- unsigned long linenum = 0, dataline = 0;
- int (*parse_line) (const char *, struct survey_record *);
- void (*print_func) (FILE *, struct survey_record *);
- G_gisinit(argv[0]);
- module = G_define_module();
- G_add_keyword(_("miscellaneous"));
- G_add_keyword(_("distance"));
- module->label = _("A simple utility for converting bearing and "
- "distance measurements to coordinates and vice versa.");
- module->description = _("It assumes a cartesian coordinate system");
- format = G_define_flag();
- format->key = 'l';
- format->description = _("Lines are labelled");
- reverse = G_define_flag();
- reverse->key = 'r';
- reverse->description =
- _("Convert from coordinates to bearing and distance");
- close = G_define_flag();
- close->key = 'c';
- close->description =
- _("Repeat the starting coordinate at the end to close a loop");
- input = G_define_standard_option(G_OPT_F_INPUT);
- input->required = NO;
- input->answer = "-";
- output = G_define_standard_option(G_OPT_F_OUTPUT);
- output->required = NO;
- output->answer = "-";
- coords = G_define_standard_option(G_OPT_M_COORDS);
- coords->description = _("Starting coordinate pair");
- coords->answer = "0.0,0.0";
- if (G_parser(argc, argv) != 0)
- exit(EXIT_FAILURE);
- if (input->answer && input->answer[0] != '-') {
- infile = fopen(input->answer, "r");
- if (infile == NULL)
- G_fatal_error(_("Couldn't open COGO file <%s>"), input->answer);
- }
- else {
- infile = stdin;
- }
- if (output->answer && output->answer[0] != '-') {
- outfile = fopen(output->answer, "w");
- if (outfile == NULL)
- G_fatal_error(_("Couldn't open output file <%s>"),
- output->answer);
- }
- else {
- outfile = stdout;
- }
- record.label[0] = '\0';
- if (format->answer) {
- record.haslabel = YES;
- }
- else {
- record.haslabel = NO;
- }
- if (reverse->answer) {
- parse_line = parse_reverse;
- print_func = print_cogo;
- }
- else {
- parse_line = parse_forward;
- print_func = print_coordinates;
- }
- if (coords->answer) {
- record.x = strtod(coords->answers[0], &ss);
- if (ss == coords->answers[0])
- G_fatal_error(_("Converting starting coordinate pair"));
- record.y = strtod(coords->answers[1], &ss);
- if (ss == coords->answers[1])
- G_fatal_error(_("Converting starting coordinate pair"));
- }
- else {
- record.x = record.y = 0.0;
- }
- while ((cptr = next_line(infile))) {
- linenum++;
- if ((cptr[0] == '#') || (cptr[0] == '\0') || (cptr[0] == '\n')) {
- /* remove \n check once module is updated to use G_getl2() */
- continue; /* line is a comment or blank */
- }
- if (!parse_line(cptr, &record)) {
- G_warning(_("Input parse error on line %lu"), linenum);
- continue;
- }
- dataline++;
- if (dataline == 1)
- first_record = record;
- print_func(outfile, &record);
- }
- if (close->answer)
- print_func(outfile, &first_record);
- if (infile != stdin)
- fclose(infile);
- if (outfile != stdout)
- fclose(stdout);
- exit(EXIT_SUCCESS);
- }
|