From a1bf953d4b8774120ec4fdcecf62082812578648 Mon Sep 17 00:00:00 2001 From: Yi Zhang Date: Mon, 24 Feb 2025 12:09:53 +0800 Subject: [PATCH] tmp --- example/CMakeLists.txt | 1 + example/cliplot_ex.cpp | 47 +++++++ lib/core/array.h | 6 - lib/graphic.h | 1 + lib/graphic/cliplot.cpp | 277 ++++++++++++++++++++++++++++++++++++++++ lib/graphic/cliplot.h | 136 ++++++++++++++++++++ 6 files changed, 462 insertions(+), 6 deletions(-) create mode 100644 example/cliplot_ex.cpp create mode 100644 lib/graphic/cliplot.cpp create mode 100644 lib/graphic/cliplot.h diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 3db6544..a02bcba 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -32,5 +32,6 @@ add_example(process_ex OFF) add_example(array_ex OFF) add_example(gmt_ex OFF) add_example(gnuplot_ex OFF) +add_example(cliplot_ex OFF) add_example(stl_io_ex OFF) add_example(ply_io_ex OFF) \ No newline at end of file diff --git a/example/cliplot_ex.cpp b/example/cliplot_ex.cpp new file mode 100644 index 0000000..bf48515 --- /dev/null +++ b/example/cliplot_ex.cpp @@ -0,0 +1,47 @@ +/******************************************************** + * ██████╗ ██████╗████████╗██╗ + * ██╔════╝ ██╔════╝╚══██╔══╝██║ + * ██║ ███╗██║ ██║ ██║ + * ██║ ██║██║ ██║ ██║ + * ╚██████╔╝╚██████╗ ██║ ███████╗ + * ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝ + * 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 . + * + * 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 "../lib/graphic/cliplot.h" + +int main(int argc, char *argv[]) +{ + double xmin = -3; + double xmax = 3; + double ymin = -1; + double ymax = 1; + + gctl::cliplot c(81, 16, xmin, xmax, ymin, ymax); + + //c.set_new_screen(true); + c.set_axis(5, 5); + c.set_digs(4); + c.set_wname("Time (s)"); + c.set_hname("Value"); + c.plot_func([](double x)->double{return sin(x);}, '.', GCTL_BOLDRED); + c.display(); + return 0; +} \ No newline at end of file diff --git a/lib/core/array.h b/lib/core/array.h index f094288..a3f7f7d 100644 --- a/lib/core/array.h +++ b/lib/core/array.h @@ -584,12 +584,6 @@ namespace gctl */ void input(const Eigen::VectorXd &b); #endif // GCTL_EIGEN - - /** - * @brief element operate function pointer - * - */ - typedef void (*foreach_a_ptr)(ArrValType &ele_ptr, size_t id); /** * @brief 并行执行指定操作 diff --git a/lib/graphic.h b/lib/graphic.h index c83887c..1c668cc 100644 --- a/lib/graphic.h +++ b/lib/graphic.h @@ -30,5 +30,6 @@ #include "graphic/gnuplot.h" #include "graphic/gmt.h" +#include "graphic/cliplot.h" #endif // _GCTL_GRAPHIC_H \ No newline at end of file diff --git a/lib/graphic/cliplot.cpp b/lib/graphic/cliplot.cpp new file mode 100644 index 0000000..5c8285c --- /dev/null +++ b/lib/graphic/cliplot.cpp @@ -0,0 +1,277 @@ +/******************************************************** + * ██████╗ ██████╗████████╗██╗ + * ██╔════╝ ██╔════╝╚══██╔══╝██║ + * ██║ ███╗██║ ██║ ██║ + * ██║ ██║██║ ██║ ██║ + * ╚██████╔╝╚██████╗ ██║ ███████╗ + * ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝ + * 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. + ******************************************************/ + +#include "cliplot.h" + +gctl::cliplot::cliplot(size_t width, size_t height, double xmin, double xmax, double ymin, double ymax) +{ + new_screen_ = false; + digs_ = 4; + xl_num_ = 5; + yl_num_ = 5; + wname_ = "X"; + hname_ = "Y"; + + struct winsize w; + ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); + width += digs_ + 1; + width_ = w.ws_col= width_ || h >= height_) return; + sym_[h*width_ + w] = sym; + att_[h*width_ + w] = att; + return; +} + +void gctl::cliplot::set_axis(int xt_num, int yt_num) +{ + xl_num_ = xt_num; + yl_num_ = yt_num; + return; +} + +void gctl::cliplot::set_digs(int digs) +{ + int old_digs = digs_; + digs_ = digs; + + width_ += digs_ - old_digs; + w0_ += digs_ - old_digs; + sym_.resize(width_*height_); + att_.resize(width_*height_); + clear(); + return; +} + +void gctl::cliplot::set_new_screen(bool new_screen) +{ + new_screen_ = new_screen; + return; +} + +void gctl::cliplot::set_wname(const std::string &wname) +{ + wname_ = wname; + return; +} + +void gctl::cliplot::set_hname(const std::string &hname) +{ + hname_ = hname; + return; +} + +std::string gctl::cliplot::axis_label(double num, int digs, int &odr) +{ + std::stringstream ss; + if (floor(log10(abs(num))) >= digs) + { + ss << std::scientific << std::setprecision(digs) << num; + odr = floor(log10(abs(num))); + if (num < 0) odr *= -1; + } + else + { + ss << std::fixed << std::setprecision(digs) << num; + odr = 0; + } + return ss.str(); +} + +void gctl::cliplot::plot_line(double x1, double x2, double y1, double y2, char s, const std::string &t) +{ + if (x1 > x2) + { + std::swap(x1, x2); + std::swap(y1, y2); + } + + for (size_t w = w0_; w < width_; w++) + { + double x = xmin_ + (w - w0_)*(xmax_ - xmin_)/(width_ - 1 - w0_); + if (x + 0.5*dx_ >= x1 && x - 0.5*dx_ <= x2) + { + double y; + if (x2 - x1 < dx_) y = y1; + else y = y1 + (y2 - y1)*(x - 0.25*dx_ - x1)/(x2 - x1); + int h1 = round(h0_ - 1 - (y - ymin_)*(h0_ - 1)/(ymax_ - ymin_)); + + if (x2 - x1 < dx_) y = y2; + else y = y1 + (y2 - y1)*(x + 0.25*dx_ - x1)/(x2 - x1); + 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; +} + +void gctl::cliplot::plot_data(const std::vector &x, const std::vector &y, char s, const std::string &t) +{ + if (x.size() != y.size()) return; + + for (size_t i = 0; i < x.size() - 1; i++) + { + plot_line(x[i], x[i+1], y[i], y[i+1], s, t); + } + return; +} + +void gctl::cliplot::display(std::ostream &os) +{ + for (size_t i = w0_; i < width_; i++) + set(i, h0_, '-', GCTL_BOLD); + + std::vector xpos(xl_num_); + int xtick = (width_ - w0_)/(xl_num_ - 1); + xpos[0] = w0_; + xpos[xl_num_ - 1] = width_ - 1; + for (size_t i = 1; i <= xl_num_ - 2; i++) + xpos[i] = w0_ + i*xtick; + + int h_digs = digs_/2; + int odr; + for (size_t i = 0; i < xl_num_; i++) + { + set(xpos[i], h0_, '|', GCTL_BOLD); + std::string xlabel = axis_label(xmin_ + (xpos[i] - w0_)*(xmax_ - xmin_)/(width_ - 1 - w0_), digs_, odr); + + for (int c = -h_digs; c <= h_digs; c++) + { + set(xpos[i] + c, h0_ + 1, xlabel[c + h_digs], GCTL_BOLD); + } + + if (odr > 0) + { + set(xpos[i] + h_digs + 1, h0_ + 1, 'e', GCTL_BOLD); + set(xpos[i] + h_digs + 3, h0_ + 1, std::to_string(odr)[0], GCTL_BOLD); + } + else if (odr < 0) + { + set(xpos[i] + h_digs + 1, h0_ + 1, 'e', GCTL_BOLD); + set(xpos[i] + h_digs + 2, h0_ + 1, std::to_string(odr)[0], GCTL_BOLD); + set(xpos[i] + h_digs + 3, h0_ + 1, std::to_string(odr)[1], GCTL_BOLD); + } + } + + for (size_t j = 0; j < h0_; j++) + { + set(w0_, j, '|', GCTL_BOLD); + } + + std::vector ypos(yl_num_); + int ytick = h0_/(yl_num_ - 1); + ypos[0] = 0; + ypos[yl_num_ - 1] = h0_ - 1; + for (size_t i = 1; i <= yl_num_ - 2; i++) + ypos[i] = i*ytick; + + for (size_t i = 0; i < yl_num_; i++) + { + set(w0_, ypos[i], '-', GCTL_BOLD); + std::string ylabel = axis_label(ymax_ - ypos[i]*(ymax_ - ymin_)/(h0_ - 1), digs_, odr); + + for (size_t c = 0; c < digs_; c++) + { + set(c, ypos[i], ylabel[c], GCTL_BOLD); + } + + if (odr > 0) + { + set(digs_ + 3, ypos[i], 'e', GCTL_BOLD); + set(digs_ + 4, ypos[i], std::to_string(odr)[0], GCTL_BOLD); + } + else if (odr < 0) + { + set(digs_ + 3, ypos[i], 'e', GCTL_BOLD); + set(digs_ + 4, ypos[i], std::to_string(odr)[0], GCTL_BOLD); + set(digs_ + 5, ypos[i], std::to_string(odr)[1], GCTL_BOLD); + } + } + + for (size_t i = 0; i < wname_.size(); i++) + { + set(width_ - wname_.size() + i, h0_ - 1, wname_[i], GCTL_BOLD); + } + + for (size_t i = 0; i < hname_.size(); i++) + { + set(w0_ + 6 + i, 0, hname_[i], GCTL_BOLD); + } + + if (new_screen_) + { + os << GCTL_CLEARALL; + GCTL_MOVEUP(os, height_); + } + + for (size_t i = 0; i < height_; i++) + { + for (size_t j = 0; j < width_; j++) + { + os << att_[i*width_ + j] << sym_[i*width_ + j] << GCTL_RESET; + } + os << std::endl; + } + return; +} \ No newline at end of file diff --git a/lib/graphic/cliplot.h b/lib/graphic/cliplot.h new file mode 100644 index 0000000..198f732 --- /dev/null +++ b/lib/graphic/cliplot.h @@ -0,0 +1,136 @@ +/******************************************************** + * ██████╗ ██████╗████████╗██╗ + * ██╔════╝ ██╔════╝╚══██╔══╝██║ + * ██║ ███╗██║ ██║ ██║ + * ██║ ██║██║ ██║ ██║ + * ╚██████╔╝╚██████╗ ██║ ███████╗ + * ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝ + * 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); + + void set_axis(int xt_num, int yt_num); + + void set_digs(int digs); + + void set_new_screen(bool new_screen); + + void set_wname(const std::string &wname); + + void set_hname(const std::string &hname); + + std::string axis_label(double num, int digs, int &odr); + + void plot_line(double x1, double x2, double y1, double y2, char s = '.', const std::string &t = GCTL_BOLDGREEN); + + template + void plot_func(FuncOp func, char s = '.', const std::string &t = GCTL_BOLDGREEN); + + void plot_data(const std::vector &x, const std::vector &y, char s = '.', const std::string &t = GCTL_BOLDGREEN); + + void display(std::ostream &os = std::cout); + + 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 \ No newline at end of file