/******************************************************** * ██████╗ ██████╗████████╗██╗ * ██╔════╝ ██╔════╝╚══██╔══╝██║ * ██║ ███╗██║ ██║ ██║ * ██║ ██║██║ ██║ ██║ * ╚██████╔╝╚██████╗ ██║ ███████╗ * ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝ * Geophysical Computational Tools & Library (GCTL) * * Copyright (c) 2023 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 . * * 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. ******************************************************/ #ifndef _GCTL_CLIPLOT_H #define _GCTL_CLIPLOT_H #include #include #include #include #include #include #include #include "../utility/stream_t.h" namespace gctl { class cliplot { public: /** * @brief 构建一个新的画布对象 * * @param width 画布宽度(大于终端宽度则取终端宽度) * @param height 画布高度(大于终端高度则取终端高度) * @param xmin x轴最小值 * @param xmax x轴最大值 * @param ymin y轴最小值 * @param ymax y轴最大值 */ cliplot(size_t width, size_t height, double xmin, double xmax, double ymin, double ymax); virtual ~cliplot(); ///< 析构函数 /** * @brief 清除画布数据 */ void clear(); /** * @brief 设置画布字符属性 * * @param w 字符列位置 * @param h 字符行位置 * @param sym 字符 * @param att 字符属性 */ void set(size_t w, size_t h, char sym, const std::string &att); /** * @brief 设置坐标轴刻度数量 * * @param xt_num x轴刻度数量 * @param yt_num y轴刻度数量 */ void set_axis(int xt_num, int yt_num); /** * @brief 设置坐标轴刻度数字位数 * * @param digs 数字位数 */ void set_digs(int digs); /** * @brief 设置是否使用新的屏幕显示画布 * * @param new_screen 是否使用新的屏幕显示画布 */ void set_new_screen(bool new_screen); /** * @brief 设置坐标轴名称 * * @param wname x轴名称 */ void set_wname(const std::string &wname); /** * @brief 设置坐标轴名称 * * @param hname y轴名称 */ void set_hname(const std::string &hname); /** * @brief 绘制直线 * * @param x1 直线起点x坐标 * @param x2 直线终点x坐标 * @param y1 直线起点y坐标 * @param y2 直线终点y坐标 * @param s 直线字符 * @param t 直线字符属性 */ void plot_line(double x1, double x2, double y1, double y2, char s = '.', const std::string &t = GCTL_BOLDGREEN); /** * @brief 绘制函数 * * @param func 函数 * @param s 函数字符 * @param t 函数字符属性 */ template void plot_func(FuncOp func, char s = '.', const std::string &t = GCTL_BOLDGREEN); /** * @brief 绘制数据 * * @param x x坐标 * @param y y坐标 * @param s 数据点字符 * @param t 数据点字符属性 */ void plot_data(const std::vector &x, const std::vector &y, char s = '.', const std::string &t = GCTL_BOLDGREEN); /** * @brief 显示画布 * * @param os 输出流 */ void display(std::ostream &os = std::cout); private: /** * @brief 计算坐标轴刻度标签 * * @param num 数值 * @param digs 数字位数 * @param odr 数值的10的幂次 * @return std::string 坐标轴刻度标签 */ std::string axis_label(double num, int digs, int &odr); /** * @brief 绘制坐标轴 */ void plot_axis(); private: bool new_screen_; int digs_; // 数字位数(包括小数点) int xl_num_; // x轴刻度数量 int yl_num_; // y轴刻度数量 double xmin_; // x轴最小值 double xmax_; // x轴最大值 double ymin_; // y轴最小值 double ymax_; // y轴最大值 double dx_, dy_; // x轴与y轴的刻度间隔 size_t w0_, h0_; // 原点的行与列位置 size_t width_; // 画布宽度 size_t height_; // 画布高度 std::vector sym_; // 画布字符 std::vector att_; // 画布字符属性 std::string wname_; std::string hname_; }; template void gctl::cliplot::plot_func(FuncOp func, char s, const std::string &t) { for (size_t w = w0_; w < width_; w++) { double y, x = xmin_ + (w - w0_)*(xmax_ - xmin_)/(width_ - 1 - w0_); y = func(x - 0.25*dx_); int h1 = round(h0_ - 1 - (y - ymin_)*(h0_ - 1)/(ymax_ - ymin_)); y = func(x + 0.25*dx_); int h2 = round(h0_ - 1 - (y - ymin_)*(h0_ - 1)/(ymax_ - ymin_)); if (h1 > h2) std::swap(h1, h2); for (size_t h = h1; h <= h2; h++) set(w, h, s, t); } return; } }; #endif // _GCTL_CLIPLOT_H