From df121c2d6fd11796084eabe231ca6c9e75f2c8f6 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Mon, 16 Jul 2018 16:32:05 +1200 Subject: [PATCH] Support exporting as CSV This is just the Survex POS output filter with a minor formatting change. --- lib/survex.pot | 15 ++++++++++++++ src/export.cc | 10 +++++++++- src/export.h | 1 + src/pos.cc | 60 +++++++++++++++++++++++++++++++++++++++++++++++++------ src/pos.h | 8 +++++--- src/printing.cc | 1 + src/survexport.cc | 20 ++++++++++--------- 7 files changed, 96 insertions(+), 19 deletions(-) diff --git a/lib/survex.pot b/lib/survex.pot index 42ffa51a..b159d983 100644 --- a/lib/survex.pot +++ b/lib/survex.pot @@ -1613,6 +1613,11 @@ msgstr "" msgid "Compass DAT and MAK files" msgstr "" +#: ../src/export.cc:72 +#: n:101 +msgid "CSV files" +msgstr "" + #: ../src/printing.cc:295 #: n:411 msgid "DXF files" @@ -1929,6 +1934,11 @@ msgstr "" msgid "bearing (90, 90d, 100g all mean 90°)" msgstr "" +#: ../src/pos.cc:93 +#: n:100 +msgid "Station Name" +msgstr "" + #: ../src/printing.cc:511 #: n:260 msgid "Station Names" @@ -3233,6 +3243,11 @@ msgstr "" msgid "station marker size (default %s)" msgstr "" +#: ../src/survexport.cc:141 +#: n:102 +msgid "produce CSV output" +msgstr "" + #: ../src/survexport.cc:102 #: n:156 msgid "produce DXF output" diff --git a/src/export.cc b/src/export.cc index d15df1de..3998bb62 100644 --- a/src/export.cc +++ b/src/export.cc @@ -69,6 +69,9 @@ // Order here needs to match order of export_format enum in export.h. const format_info export_format_info[] = { + { ".csv", /*CSV files*/101, + LABELS|ENTS|FIXES|EXPORTS|EXPORT_3D, + LABELS }, { ".dxf", /*DXF files*/411, LABELS|LEGS|SURF|SPLAYS|STNS|PASG|XSECT|WALLS|MARKER_SIZE|TEXT_HEIGHT|GRID|FULL_COORDS, LABELS|LEGS|STNS }, @@ -1337,6 +1340,11 @@ Export(const wxString &fnm_out, const wxString &title, bool need_bounds = true; ExportFilter * filt; switch (format) { + case FMT_CSV: + filt = new POS(model.GetSeparator(), true); + show_mask |= FULL_COORDS; + need_bounds = false; + break; case FMT_DXF: filt = new DXF(text_height); break; @@ -1369,7 +1377,7 @@ Export(const wxString &fnm_out, const wxString &title, show_mask |= FULL_COORDS; break; case FMT_POS: - filt = new POS(model.GetSeparator()); + filt = new POS(model.GetSeparator(), false); show_mask |= FULL_COORDS; need_bounds = false; break; diff --git a/src/export.h b/src/export.h index 170e840d..b8970422 100644 --- a/src/export.h +++ b/src/export.h @@ -30,6 +30,7 @@ class SurveyFilter; // Order here needs to match order of extension array in export.cc. typedef enum { + FMT_CSV, FMT_DXF, FMT_EPS, FMT_GPX, diff --git a/src/pos.cc b/src/pos.cc index fa577b88..e355905f 100644 --- a/src/pos.cc +++ b/src/pos.cc @@ -1,5 +1,5 @@ /* pos.cc - * Export from Aven as Survex .pos. + * Export from Aven as Survex .pos or .csv. */ /* Copyright (C) 2001,2002,2011,2013,2014,2015,2018 Olly Betts * @@ -37,6 +37,35 @@ using namespace std; +static void +csv_quote(const char* s, FILE* fh) +{ + size_t i = 0; + while (true) { + switch (s[i]) { + case '\0': + fputs(s, fh); + return; + case ',': + case '"': + case '\r': + case '\n': + break; + } + ++i; + } + PUTC('"', fh); + fwrite(s, i, 1, fh); + while (s[i]) { + // Double up any " in the string to escape them. + if (s[i] == '"') + PUTC(s[i], fh); + PUTC(s[i], fh); + ++i; + } + PUTC('"', fh); +} + POS::~POS() { vector::const_iterator i; @@ -56,9 +85,22 @@ POS::passes() const void POS::header(const char *, const char *, time_t, double, double, double, double, double, double) { - /* TRANSLATORS: Heading line for .pos file. Please try to ensure the “,”s - * (or at least the columns) are in the same place */ - fputsnl(msg(/*( Easting, Northing, Altitude )*/195), fh); + if (csv) { + bool comma = false; + for (int msgno : { /*Easting*/378, + /*Northing*/379, + /*Altitude*/335, + /*Station Name*/100 }) { + if (comma) PUTC(',', fh); + csv_quote(msg(msgno), fh); + comma = true; + } + PUTC('\n', fh); + } else { + /* TRANSLATORS: Heading line for .pos file. Please try to ensure the + * “,”s (or at least the columns) are in the same place */ + fputsnl(msg(/*( Easting, Northing, Altitude )*/195), fh); + } } void @@ -92,7 +134,13 @@ POS::footer() sort(todo.begin(), todo.end(), pos_label_ptr_cmp(separator)); vector::const_iterator i; for (i = todo.begin(); i != todo.end(); ++i) { - fprintf(fh, "(%8.2f, %8.2f, %8.2f ) %s\n", - (*i)->x, (*i)->y, (*i)->z, (*i)->name); + if (csv) { + fprintf(fh, "%.2f,%.2f,%.2f,", (*i)->x, (*i)->y, (*i)->z); + csv_quote((*i)->name, fh); + PUTC('\n', fh); + } else { + fprintf(fh, "(%8.2f, %8.2f, %8.2f ) %s\n", + (*i)->x, (*i)->y, (*i)->z, (*i)->name); + } } } diff --git a/src/pos.h b/src/pos.h index 30bae226..b8f3f7a9 100644 --- a/src/pos.h +++ b/src/pos.h @@ -1,8 +1,8 @@ /* pos.h - * Export from Aven as Survex .pos. + * Export from Aven as Survex .pos or .csv. */ -/* Copyright (C) 2005,2013,2014,2015 Olly Betts +/* Copyright (C) 2005,2013,2014,2015,2018 Olly Betts * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,8 +35,10 @@ class POS : public ExportFilter { char separator; + bool csv; + public: - explicit POS(char separator_) : separator(separator_) { } + POS(char separator_, bool csv_) : separator(separator_), csv(csv_) { } ~POS(); const int * passes() const; void header(const char *, const char *, time_t, diff --git a/src/printing.cc b/src/printing.cc index 9b5568f5..a656ccc1 100644 --- a/src/printing.cc +++ b/src/printing.cc @@ -267,6 +267,7 @@ static wxString scales[] = { // The order of these arrays must match export_format in export.h. static wxString formats[] = { + wxT("CVS"), wxT("DXF"), wxT("EPS"), wxT("GPX"), diff --git a/src/survexport.cc b/src/survexport.cc index f71824a3..3176b669 100644 --- a/src/survexport.cc +++ b/src/survexport.cc @@ -90,6 +90,7 @@ main(int argc, char **argv) {"grid", optional_argument, 0, 'g'}, {"text-height", required_argument, 0, 't'}, {"marker-size", required_argument, 0, 'm'}, + {"csv", no_argument, 0, OPT_FMT_BASE + FMT_CSV}, {"dxf", no_argument, 0, OPT_FMT_BASE + FMT_DXF}, {"eps", no_argument, 0, OPT_FMT_BASE + FMT_EPS}, {"gpx", no_argument, 0, OPT_FMT_BASE + FMT_GPX}, @@ -137,20 +138,21 @@ main(int argc, char **argv) {HLP_ENCODELONG(21), /*generate grid (default %sm)*/148, STRING(DEFAULT_GRID_SPACING)}, {HLP_ENCODELONG(22), /*station labels text height (default %s)*/149, STRING(DEFAULT_TEXT_HEIGHT)}, {HLP_ENCODELONG(23), /*station marker size (default %s)*/152, STRING(DEFAULT_MARKER_SIZE)}, - {HLP_ENCODELONG(24), /*produce DXF output*/156, 0}, - {HLP_ENCODELONG(25), /*produce EPS output*/454, 0}, - {HLP_ENCODELONG(26), /*produce GPX output*/455, 0}, - {HLP_ENCODELONG(27), /*produce HPGL output*/456, 0}, + {HLP_ENCODELONG(24), /*produce CSV output*/102, 0}, + {HLP_ENCODELONG(25), /*produce DXF output*/156, 0}, + {HLP_ENCODELONG(26), /*produce EPS output*/454, 0}, + {HLP_ENCODELONG(27), /*produce GPX output*/455, 0}, + {HLP_ENCODELONG(28), /*produce HPGL output*/456, 0}, {HLP_ENCODELONG(29), /*produce JSON output*/457, 0}, - {HLP_ENCODELONG(29), /*produce KML output*/458, 0}, + {HLP_ENCODELONG(30), /*produce KML output*/458, 0}, /* TRANSLATORS: "Compass" and "Carto" are the names of software packages, * so should not be translated. */ - {HLP_ENCODELONG(30), /*produce Compass PLT output for Carto*/159, 0}, + {HLP_ENCODELONG(31), /*produce Compass PLT output for Carto*/159, 0}, /* TRANSLATORS: "Skencil" is the name of a software package, so should not be * translated. */ - {HLP_ENCODELONG(31), /*produce Skencil output*/158, 0}, - {HLP_ENCODELONG(32), /*produce Survex POS output*/459, 0}, - {HLP_ENCODELONG(33), /*produce SVG output*/160, 0}, + {HLP_ENCODELONG(32), /*produce Skencil output*/158, 0}, + {HLP_ENCODELONG(33), /*produce Survex POS output*/459, 0}, + {HLP_ENCODELONG(34), /*produce SVG output*/160, 0}, {0, 0, 0} }; -- 2.11.4.GIT