380 lines
11 KiB
C++
380 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/geometry.h"
|
|
#include "gctl/io.h"
|
|
#include "gctl/utility.h"
|
|
|
|
class HandyMan
|
|
{
|
|
public:
|
|
HandyMan();
|
|
virtual ~HandyMan();
|
|
|
|
void Routine(); // Caller of all sub-routines.
|
|
void SR_CalPlaneCoeff(); // Galculate 3D planes' coefficents.
|
|
void SR_RGB2CPT(); // Convert RGB series to color palette tables (.cpt) file.
|
|
void SR_MgNumber(); // Calculate the magnesium number (Mg#).
|
|
void SR_Sequent(); // Output sequent arrays in column formats.
|
|
void SR_GeoAngle(); // Calculate the geo-centric angle of two points on the sphere.
|
|
};
|
|
|
|
HandyMan::HandyMan(){}
|
|
|
|
HandyMan::~HandyMan(){}
|
|
|
|
void HandyMan::Routine()
|
|
{
|
|
int c;
|
|
std::cout << "What do you want to do?\n\
|
|
(0) Quit.\n\
|
|
(1) Calculate coefficients of a 3-D plane.\n\
|
|
(2) Convert RGB series to .cpt file.\n\
|
|
(3) Calculate the magnesium number (Mg#).\n\
|
|
(4) Output sequent arrays in column formats.\n\
|
|
(5) Calculate the geo-centric angle of two points on the sphere.\n";
|
|
std::cout << ">> ";
|
|
std::cin >> c;
|
|
|
|
switch (c)
|
|
{
|
|
case 1:
|
|
SR_CalPlaneCoeff(); break;
|
|
case 2:
|
|
SR_RGB2CPT(); break;
|
|
case 3:
|
|
SR_MgNumber(); break;
|
|
case 4:
|
|
SR_Sequent(); break;
|
|
case 5:
|
|
SR_GeoAngle(); break;
|
|
default:
|
|
throw std::runtime_error("Invalid choice. From gctl::handyman.");
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
void HandyMan::SR_CalPlaneCoeff()
|
|
{
|
|
int c;
|
|
std::cout << "Known points?\n\
|
|
(1) Three points in the Cartesian coordinates.\n\
|
|
(2) Two points on a spherical surface.\n";
|
|
std::cout << ">> ";
|
|
std::cin >> c;
|
|
|
|
double A, B, C, D;
|
|
|
|
if (c == 1)
|
|
{
|
|
std::cout << "Input x, y, and z coordinates of the points.\n";
|
|
|
|
gctl::point3dc c[3];
|
|
for (size_t i = 0; i < 3; i++)
|
|
{
|
|
std::cout << ">> ";
|
|
std::cin >> c[i];
|
|
}
|
|
|
|
gctl::geometry3d::get_plane_coeff(c[0].x, c[1].x, c[2].x, c[0].y, c[1].y, c[2].y, c[0].z, c[1].z, c[2].z, A, B, C, D);
|
|
}
|
|
else if (c == 2)
|
|
{
|
|
std::cout << "Input radius, longitude, and latitude coordinates of the points.\n";
|
|
|
|
gctl::point3ds c[2];
|
|
for (size_t i = 0; i < 2; i++)
|
|
{
|
|
std::cout << ">> ";
|
|
std::cin >> c[i];
|
|
}
|
|
|
|
gctl::geometry3d::get_plane_coeff(c[0], c[1], A, B, C, D);
|
|
}
|
|
else throw std::runtime_error("Invalid choice. From gctl::handyman.");
|
|
|
|
if (A != 0.0)
|
|
{
|
|
B /= A; C /= A; D /= A; A = 1.0;
|
|
}
|
|
else if (B != 0.0)
|
|
{
|
|
A /= B; C /= B; D /= B; B = 1.0;
|
|
}
|
|
else if (C != 0.0)
|
|
{
|
|
A /= C; B /= C; D /= C; C = 1.0;
|
|
}
|
|
else throw std::runtime_error("Invalid plane's coefficients. From gctl::handyman.");
|
|
|
|
std::cout << "Plane's equation:\n";
|
|
std::cout << std::fixed << std::setprecision(3) << A << "*x + " << B << "*y + " << C << "*z + " << D << " = 0\n";
|
|
return;
|
|
}
|
|
|
|
void HandyMan::SR_RGB2CPT()
|
|
{
|
|
gctl::dsv_io tc;
|
|
std::string rgb_file, cpt_file;
|
|
std::cout << "Name of the RGB series file (Each line of file contains a R G B group).\n>> ";
|
|
std::cin >> rgb_file;
|
|
|
|
std::cout << "Name of the output .cpt file.\n>> ";
|
|
std::cin >> cpt_file;
|
|
|
|
tc.load_text(rgb_file);
|
|
int c_size = tc.row_number();
|
|
|
|
gctl::array<double> R, G, B;
|
|
tc.get_column(R, 0);
|
|
tc.get_column(G, 1);
|
|
tc.get_column(B, 2);
|
|
|
|
int i_type;
|
|
std::cout << "Interpolation type of the interval values.\n(1) linear\n(2) data\n>> ";
|
|
std::cin >> i_type;
|
|
|
|
int sym_zero = 0;
|
|
std::cout << "symmetric w.r.t. zero value (1 for yes and 0 for no).\n>> ";
|
|
std::cin >> sym_zero;
|
|
|
|
std::ofstream ofile;
|
|
gctl::open_outfile(ofile, cpt_file, ".cpt");
|
|
|
|
double dn_val, up_val;
|
|
double mini, maxi;
|
|
if (i_type == 1)
|
|
{
|
|
if (sym_zero)
|
|
{
|
|
std::cout << "Maximal absolute value of the output .cpt file.\n>> ";
|
|
std::cin >> maxi;
|
|
mini = -1.0*maxi;
|
|
}
|
|
else
|
|
{
|
|
std::cout << "Minimal and maximal values of the output .cpt file.\n>> ";
|
|
std::cin >> mini >> maxi;
|
|
}
|
|
|
|
ofile << "# This file is generated by the tool 'handyman' of the GCTL package.\n";
|
|
ofile << "# Input file: " << rgb_file << "\n";
|
|
ofile << "# Interpolation type: linear\n";
|
|
ofile << "# symmetric w.r.t. zero value: " << sym_zero << "\n";
|
|
|
|
for (size_t i = 0; i < c_size - 1; i++)
|
|
{
|
|
dn_val = (maxi - mini)*i/(c_size - 1.0) + mini;
|
|
up_val = (maxi - mini)*(i + 1.0)/(c_size - 1.0) + mini;
|
|
|
|
ofile << dn_val << " " << R[i] << "/" << G[i] << "/" << B[i] << " ";
|
|
ofile << up_val << " " << R[i+1] << "/" << G[i+1] << "/" << B[i+1] << " L\n";
|
|
}
|
|
|
|
ofile << "B black\nF white\nN 128\n";
|
|
}
|
|
else if (i_type == 2)
|
|
{
|
|
std::string in_str, f_name;
|
|
std::cout << "Name of the .txt input file.\n>> ";
|
|
std::cin >> in_str;
|
|
|
|
gctl::parse_string_to_value(in_str, '+', true, f_name);
|
|
|
|
tc.clear();
|
|
tc.load_text(f_name);
|
|
|
|
gctl::array<double> D_ori;
|
|
tc.get_column(D_ori, 0);
|
|
|
|
std::vector<double> D;
|
|
D.reserve(D_ori.size());
|
|
for (size_t i = 0; i < D_ori.size(); i++)
|
|
{
|
|
if (!std::isnan(D_ori[i]))
|
|
{
|
|
D.push_back(D_ori[i]);
|
|
}
|
|
}
|
|
|
|
int d_size = D.size();
|
|
int box_size = ceil(d_size/(c_size - 1.0));
|
|
|
|
// 排序
|
|
std::sort(D.begin(), D.end());
|
|
mini = D.front(); maxi = D.back();
|
|
|
|
if (sym_zero)
|
|
{
|
|
if (abs(maxi) > abs(mini))
|
|
{
|
|
mini = -1.0*maxi;
|
|
D.insert(D.begin(), mini);
|
|
}
|
|
else if (abs(maxi) < abs(mini))
|
|
{
|
|
maxi = -1.0*mini;
|
|
D.push_back(maxi);
|
|
}
|
|
|
|
d_size = D.size();
|
|
box_size = ceil(d_size/(c_size - 1.0));
|
|
}
|
|
|
|
ofile << "# This file is generated by the tool 'handyman' of the GCTL package.\n";
|
|
ofile << "# Input file: " << rgb_file << "\n";
|
|
ofile << "# Interpolation type: data\n";
|
|
ofile << "# symmetric w.r.t. zero value: " << sym_zero << "\n";
|
|
ofile << "# data name: " << in_str << "\n";
|
|
|
|
int d_id;
|
|
dn_val = mini;
|
|
for (size_t i = 0; i < c_size - 1; i++)
|
|
{
|
|
d_id = box_size*(i+1) - 1;
|
|
|
|
if (d_id >= d_size) d_id = d_size - 1;
|
|
up_val = D[d_id];
|
|
|
|
ofile << dn_val << " " << R[i] << "/" << G[i] << "/" << B[i] << " ";
|
|
ofile << up_val << " " << R[i+1] << "/" << G[i+1] << "/" << B[i+1] << " L\n";
|
|
|
|
dn_val = up_val;
|
|
}
|
|
|
|
ofile << "B black\nF white\nN 128\n";
|
|
}
|
|
else throw std::runtime_error("Invalid choice. From gctl::handyman.");
|
|
|
|
ofile.close();
|
|
return;
|
|
}
|
|
|
|
void HandyMan::SR_MgNumber()
|
|
{
|
|
double feo, fe2o3, mgo;
|
|
std::cout << "Weight precents (wt%) of MgO (> 0), FeO (>= 0) and Fe2O3 (>= 0).\n>> ";
|
|
std::cin >> mgo >> feo >> fe2o3;
|
|
|
|
if (mgo <= 0.0 || feo < 0.0 || fe2o3 < 0.0)
|
|
{
|
|
throw std::runtime_error("Invalid inputs.");
|
|
}
|
|
|
|
feo += 0.8998*fe2o3;
|
|
|
|
std::cout << "Mg# = " << (mgo/40.3044)/(mgo/40.3044 + feo/71.8444) << "\n";
|
|
return;
|
|
}
|
|
|
|
void HandyMan::SR_Sequent()
|
|
{
|
|
double st, ed, inter;
|
|
std::vector<double> starts, ends, intervals;
|
|
|
|
std::cout << "Input column's start, end and interval values (one group per line, enter empty line to finish).\n";
|
|
|
|
std::string line;
|
|
std::getline(std::cin, line);
|
|
while (std::getline(std::cin, line))
|
|
{
|
|
if (line.empty()) break;
|
|
else
|
|
{
|
|
gctl::parse_string_to_value(line, ' ', true, st, ed, inter);
|
|
starts.push_back(st);
|
|
ends.push_back(ed);
|
|
intervals.push_back(inter);
|
|
}
|
|
}
|
|
|
|
int l = 0;
|
|
bool valid;
|
|
do
|
|
{
|
|
valid = false;
|
|
for (size_t i = 0; i < starts.size(); i++)
|
|
{
|
|
st = starts[i] + l*intervals[i];
|
|
|
|
if (starts[i] != ends[i] && st <= ends[i])
|
|
{
|
|
std::cout << st << " ";
|
|
valid = true;
|
|
}
|
|
else if (starts[i] == ends[i] && valid == true)
|
|
{
|
|
std::cout << st << " ";
|
|
}
|
|
}
|
|
std::cout << "\n";
|
|
|
|
l++;
|
|
}
|
|
while (valid);
|
|
return;
|
|
}
|
|
|
|
void HandyMan::SR_GeoAngle()
|
|
{
|
|
std::cout << "Input longitude, and latitude coordinates of the two points.\n";
|
|
|
|
gctl::point3ds c[2];
|
|
for (size_t i = 0; i < 2; i++)
|
|
{
|
|
std::cout << ">> ";
|
|
c[i].rad = 1.0;
|
|
std::cin >> c[i].lon >> c[i].lat;
|
|
}
|
|
|
|
std::cout << "The geo-centric angle is: " << gctl::geometry3d::angle(c[0].s2c(), c[1].s2c())*180.0/M_PI << " deg.\n";
|
|
return;
|
|
}
|
|
|
|
int main(int argc, char const *argv[]) try
|
|
{
|
|
HandyMan hm;
|
|
|
|
gctl::display_logo();
|
|
|
|
bool quit = false;
|
|
while (!quit)
|
|
{
|
|
hm.Routine();
|
|
|
|
std::cout << "Quit? (1 for yes and 0 for no)\n";
|
|
std::cout << ">> ";
|
|
std::cin >> quit;
|
|
}
|
|
return 0;
|
|
}
|
|
catch (std::exception &e)
|
|
{
|
|
GCTL_ShowWhatError(e.what(), GCTL_ERROR_ERROR, 0, 0, 0);
|
|
} |