339 lines
11 KiB
C++
339 lines
11 KiB
C++
/********************************************************
|
|
* ██████╗ ██████╗████████╗██╗
|
|
* ██╔════╝ ██╔════╝╚══██╔══╝██║
|
|
* ██║ ███╗██║ ██║ ██║
|
|
* ██║ ██║██║ ██║ ██║
|
|
* ╚██████╔╝╚██████╗ ██║ ███████╗
|
|
* ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝
|
|
* Geophysical Computational Tools & Library (GCTL)
|
|
*
|
|
* Copyright (c) 2022 Yi Zhang (yizhang-geo@zju.edu.cn)
|
|
*
|
|
* GCTL is distributed under a dual licensing scheme. You can redistribute
|
|
* it and/or modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation, either version 2
|
|
* of the License, or (at your option) any later version. You should have
|
|
* received a copy of the GNU Lesser General Public License along with this
|
|
* program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* If the terms and conditions of the LGPL v.2. would prevent you from using
|
|
* the GCTL, please consider the option to obtain a commercial license for a
|
|
* fee. These licenses are offered by the GCTL's original author. As a rule,
|
|
* licenses are provided "as-is", unlimited in time for a one time fee. Please
|
|
* send corresponding requests to: yizhang-geo@zju.edu.cn. Please do not forget
|
|
* to include some description of your company and the realm of its activities.
|
|
* Also add information on how to contact you by electronic and paper mail.
|
|
******************************************************/
|
|
|
|
#include "gctl/core.h"
|
|
#include "gctl/io.h"
|
|
#include "gctl/utility.h"
|
|
|
|
int main(int argc, char *argv[]) try
|
|
{
|
|
std::string v_str = "Treate all input columns as grid values. Set exact specification of incoming column value table(s). \
|
|
Append two chars that indicate file organization: (1) If data is in row format, state if first row is at T(op) or B(ottom). \
|
|
Then, append L or R to indicate starting point in row. (2) If data is in column format, state if first columns is \
|
|
L(left) or R(ight). Then, append T or B to indicate starting point in column.";
|
|
|
|
gctl::flags_parser fp;
|
|
fp.set_proname("xyz2nc");
|
|
fp.set_proinfo("Read xyz data table and write the Netcdf .nc grid files. \
|
|
This program is a toolkit of the GCTL package. The GCTL comes with ABSOLUTE NO WARRANTY. \
|
|
Please see instructions or contact the author for more information.");
|
|
fp.add_opt('t', "table", required_argument, NULL, "Input data table.", "<table>", true);
|
|
fp.add_opt('r', "range", required_argument, NULL, "Range of the output grid.", "<xmin>/<xmax>/<ymin>/<ymax>", true);
|
|
fp.add_opt('i', "interval", required_argument, NULL, "Intervals of output grid", "<dx>/<dy>", false);
|
|
fp.add_opt('s', "size", required_argument, NULL, "Size of the output grid.", "<x-size>/<y-size>", false);
|
|
fp.add_opt('g', "grid", required_argument, NULL, "Output grid file. The input table name will be used if not set.", "<grid>", false);
|
|
fp.add_opt('c', "column", required_argument, NULL, "Column index of x, y and data. The defaults are 0,1,2. Append extra columns to save multiple grids in one file.", "<x-col>,<y-col>,<z-col>,...", false);
|
|
fp.add_opt('v', "value-only", required_argument, NULL, v_str.c_str(), "T|B|L|R", false);
|
|
fp.add_opt('l', "label", required_argument, NULL, "Labels of x, y and data. The defaults are 'x', 'y' and 'z'.", "<x-label>,<y-label>,<z-label>,...", false);
|
|
fp.add_opt('e', "head-record", required_argument, NULL, "Input file has [0] Header record(s).", "<size>", false);
|
|
fp.add_opt('a', "annotate", required_argument, NULL, "The starting symbol of an annotate line. The default is '#'.", "<sym>", false);
|
|
fp.add_opt('d', "delimeter", required_argument, NULL, "Delimeter between different columns. The default is space.", "<sym>", false);
|
|
fp.add_opt('h', "help", no_argument, NULL, "Show help information.", 0, false);
|
|
fp.configure(argc, argv);
|
|
|
|
if (argc == 1 || fp.set_opt('h'))
|
|
{
|
|
fp.show_help_page();
|
|
return 0;
|
|
}
|
|
|
|
std::string table_name, range_str, interval_str, size_str, grid_name, col_str, label_str, head_str, ant_str, del_str, format_str;
|
|
fp.get_argv({'t', 'r', 'i', 's', 'g', 'c', 'l', 'e', 'a', 'd', 'v'},
|
|
{&table_name, &range_str, &interval_str, &size_str, &grid_name, &col_str, &label_str, &head_str, &ant_str, &del_str, &format_str});
|
|
// 查看是否通过强制参数检查
|
|
if (!fp.pass_mandatory()) return 0;
|
|
|
|
if (grid_name == "NULL")
|
|
{
|
|
size_t dpos = table_name.find_last_of('.');
|
|
if (dpos != std::string::npos) grid_name = table_name.substr(0, dpos);
|
|
else grid_name = table_name;
|
|
}
|
|
|
|
if (col_str == "NULL") col_str = "0,1,2";
|
|
|
|
bool custom_label = false;
|
|
if (label_str == "NULL") label_str = "x,y,z";
|
|
else custom_label = true;
|
|
|
|
bool value_only = false;
|
|
if (format_str != "NULL") value_only = true;
|
|
|
|
std::string file_ext;
|
|
size_t dpos = table_name.find_last_of('.');
|
|
if (dpos != std::string::npos)
|
|
{
|
|
file_ext = table_name.substr(dpos);
|
|
table_name = table_name.substr(0, dpos);
|
|
}
|
|
else file_ext = ".txt";
|
|
|
|
gctl::text_descriptor desc;
|
|
desc.file_name_ = table_name;
|
|
desc.file_ext_ = file_ext;
|
|
if (head_str != "NULL") gctl::str2type(head_str, desc.head_num_);
|
|
if (ant_str != "NULL") gctl::str2type(ant_str, desc.att_sym_);
|
|
if (del_str != "NULL") gctl::str2type(del_str, desc.delimiter_);
|
|
if (grid_name == "NULL") grid_name = table_name;
|
|
|
|
if (interval_str == "NULL" && size_str == "NULL")
|
|
{
|
|
throw gctl::runtime_error("Either the data intervals or table sizes must be set. See the instructions for more information.");
|
|
}
|
|
|
|
int tmp_int, maxi_col = -1;
|
|
std::string tmp_str;
|
|
|
|
gctl::_1i_vector col_index;
|
|
std::stringstream tmp_ss;
|
|
gctl::str2ss(col_str, tmp_ss, ",");
|
|
while (tmp_ss >> tmp_int)
|
|
{
|
|
col_index.push_back(tmp_int);
|
|
maxi_col = GCTL_MAX(maxi_col, tmp_int);
|
|
}
|
|
|
|
gctl::_1s_vector label_index;
|
|
gctl::str2ss(label_str, tmp_ss, ",");
|
|
while (tmp_ss >> tmp_str)
|
|
{
|
|
label_index.push_back(tmp_str);
|
|
}
|
|
|
|
if (!value_only && col_index.size() < 3)
|
|
{
|
|
GCTL_ShowWhatError("Not enough column index found:", GCTL_ERROR_ERROR,
|
|
col_str.c_str(), "Use -h option to see the instruction.", 0);
|
|
return 0;
|
|
}
|
|
|
|
if (label_index.size() < 3)
|
|
{
|
|
GCTL_ShowWhatError("Not enough column labels found:", GCTL_ERROR_ERROR,
|
|
label_str.c_str(), "Use -h option to see the instruction.", 0);
|
|
return 0;
|
|
}
|
|
|
|
if (custom_label && col_index.size() != label_index.size())
|
|
{
|
|
GCTL_ShowWhatError("Number of index and labels not match.", GCTL_ERROR_ERROR,
|
|
0, "Use -h option to see the instruction.", 0);
|
|
return 0;
|
|
}
|
|
|
|
gctl::_2d_vector table_data;
|
|
gctl::read_text2vector2d(desc, table_data);
|
|
|
|
// check data
|
|
for (int i = 0; i < table_data.size(); i++)
|
|
{
|
|
if (table_data[i].size() < maxi_col+1)
|
|
{
|
|
GCTL_ShowWhatError("Incomplete data set found in:", GCTL_ERROR_ERROR, table_name.c_str(), 0, 0);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int xnum, ynum;
|
|
double xmin, xmax, ymin, ymax, dx, dy;
|
|
gctl::parse_string_to_value(range_str, '/', true, xmin, xmax, ymin, ymax);
|
|
|
|
if (interval_str != "NULL")
|
|
{
|
|
gctl::parse_string_to_value(interval_str, '/', true, dx, dy);
|
|
xnum = round((xmax - xmin)/dx) + 1;
|
|
ynum = round((ymax - ymin)/dy) + 1;
|
|
}
|
|
else
|
|
{
|
|
gctl::parse_string_to_value(size_str, '/', true, xnum, ynum);
|
|
dx = (xmax - xmin)/(xnum - 1.0);
|
|
dy = (ymax - ymin)/(ynum - 1.0);
|
|
}
|
|
|
|
gctl::array<double> out_data(xnum*ynum, GCTL_BDL_MAX);
|
|
|
|
int tmp_M, tmp_N;
|
|
|
|
if (value_only)
|
|
{
|
|
gctl::array<int> val_idx(table_data.size());
|
|
if (format_str == "TL")
|
|
{
|
|
for (int i = 0; i < ynum; i++)
|
|
{
|
|
for (int j = 0; j < xnum; j++)
|
|
{
|
|
val_idx[j + xnum*i] = xnum*(ynum - 1 - i) + j;
|
|
}
|
|
}
|
|
}
|
|
else if (format_str == "TR")
|
|
{
|
|
for (int i = 0; i < ynum; i++)
|
|
{
|
|
for (int j = 0; j < xnum; j++)
|
|
{
|
|
val_idx[j + xnum*i] = xnum*(ynum - 1 - i) + xnum - 1 - j;
|
|
}
|
|
}
|
|
}
|
|
else if (format_str == "BL")
|
|
{
|
|
for (int i = 0; i < val_idx.size(); i++)
|
|
{
|
|
val_idx[i] = i;
|
|
}
|
|
}
|
|
else if (format_str == "BR")
|
|
{
|
|
for (int i = 0; i < ynum; i++)
|
|
{
|
|
for (int j = 0; j < xnum; j++)
|
|
{
|
|
val_idx[j + xnum*i] = xnum*i + xnum - 1 - j;
|
|
}
|
|
}
|
|
}
|
|
else if (format_str == "LT")
|
|
{
|
|
for (int j = 0; j < xnum; j++)
|
|
{
|
|
for (int i = 0; i < ynum; i++)
|
|
{
|
|
val_idx[i + ynum*j] = xnum*(ynum - 1 - i) + j;
|
|
}
|
|
}
|
|
}
|
|
else if (format_str == "RT")
|
|
{
|
|
for (int j = 0; j < xnum; j++)
|
|
{
|
|
for (int i = 0; i < ynum; i++)
|
|
{
|
|
val_idx[i + ynum*j] = xnum*(ynum - 1 - i) + xnum - 1 - j;
|
|
}
|
|
}
|
|
}
|
|
else if (format_str == "LB")
|
|
{
|
|
for (int j = 0; j < xnum; j++)
|
|
{
|
|
for (int i = 0; i < ynum; i++)
|
|
{
|
|
val_idx[i + ynum*j] = xnum*i + j;
|
|
}
|
|
}
|
|
}
|
|
else if (format_str == "RB")
|
|
{
|
|
for (int j = 0; j < xnum; j++)
|
|
{
|
|
for (int i = 0; i < ynum; i++)
|
|
{
|
|
val_idx[i + ynum*j] = xnum*i + xnum - 1 - j;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < table_data.size(); i++)
|
|
{
|
|
out_data[val_idx[i]] = table_data[i][col_index[0]];
|
|
}
|
|
|
|
gctl::save_netcdf_grid(grid_name, out_data, xnum, ynum, xmin, dx, ymin, dy,
|
|
label_index[0], label_index[1], label_index[2]);
|
|
|
|
std::string save_dataname;
|
|
if (col_index.size() > 1)
|
|
{
|
|
for (int c = 1; c < col_index.size(); c++)
|
|
{
|
|
out_data.assign(GCTL_BDL_MAX);
|
|
|
|
for (int i = 0; i < table_data.size(); i++)
|
|
{
|
|
out_data[val_idx[i]] = table_data[i][col_index[c]];
|
|
}
|
|
|
|
if (custom_label)
|
|
save_dataname = label_index[c];
|
|
else
|
|
save_dataname = label_index[2] + "_" + std::to_string(c-1);
|
|
gctl::append_netcdf_grid(grid_name, out_data, label_index[0], label_index[1], save_dataname);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < table_data.size(); i++)
|
|
{
|
|
if (table_data[i][col_index[0]] >= xmin && table_data[i][col_index[0]] <= xmax &&
|
|
table_data[i][col_index[1]] >= ymin && table_data[i][col_index[1]] <= ymax)
|
|
{
|
|
tmp_N = round((table_data[i][col_index[0]] - xmin)/dx);
|
|
tmp_M = round((table_data[i][col_index[1]] - ymin)/dy);
|
|
out_data[tmp_M*xnum + tmp_N] = table_data[i][col_index[2]];
|
|
}
|
|
}
|
|
|
|
gctl::save_netcdf_grid(grid_name, out_data, xnum, ynum, xmin, dx, ymin, dy,
|
|
label_index[0], label_index[1], label_index[2]);
|
|
|
|
std::string save_dataname;
|
|
if (col_index.size() > 3)
|
|
{
|
|
for (int c = 3; c < col_index.size(); c++)
|
|
{
|
|
out_data.assign(GCTL_BDL_MAX);
|
|
|
|
for (int i = 0; i < table_data.size(); i++)
|
|
{
|
|
if (table_data[i][col_index[0]] >= xmin && table_data[i][col_index[0]] <= xmax &&
|
|
table_data[i][col_index[1]] >= ymin && table_data[i][col_index[1]] <= ymax)
|
|
{
|
|
tmp_N = round((table_data[i][col_index[0]] - xmin)/dx);
|
|
tmp_M = round((table_data[i][col_index[1]] - ymin)/dy);
|
|
out_data[tmp_M*xnum + tmp_N] = table_data[i][col_index[c]];
|
|
}
|
|
}
|
|
|
|
if (custom_label)
|
|
save_dataname = label_index[c];
|
|
else
|
|
save_dataname = label_index[2] + "_" + std::to_string(c-1);
|
|
gctl::append_netcdf_grid(grid_name, out_data, label_index[0], label_index[1], save_dataname);
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
catch(std::exception &e)
|
|
{
|
|
GCTL_ShowWhatError(e.what(), GCTL_ERROR_ERROR, 0, 0, 0);
|
|
} |