美文网首页
C++ 使用matplotlib绘图

C++ 使用matplotlib绘图

作者: FredricZhu | 来源:发表于2024-04-09 15:55 被阅读0次

    众所周知,python可以使用matplotlib库实现比较简单的绘图操作。
    本例使用C++ 调用python的matplotlib库,实现简单的绘图操作。
    本例使用conanio/gcc9的镜像来实现使用C++调用python matplotlib库的操作。
    使用conan镜像的原因是比较容易完成对C++的依赖设置,而且大家也比较容易克隆出相同的环境来实现效果。
    本例的实现是使用docker镜像来完成,代码是跨平台可用的。
    实现步骤,

    1. 在coanio/gcc9容器中安装matplotlib
    pip install matplotlib
    
    1. 使用如下CMakeLists.txt文件
      注意需要链接上该环境中的python3.7m的相关头文件和库文件
    cmake_minimum_required(VERSION 3.3)
    
    
    project(45_matplot_lib)
    
    set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:/usr/local/lib/pkgconfig/")
    
    set ( CMAKE_CXX_FLAGS "-pthread")
    set(CMAKE_CXX_STANDARD 17)
    add_definitions(-g)
    
    add_definitions(-DSAVE_PERCEPTION_CONCAT_IMG)
    
    include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
    conan_basic_setup()
    
    include_directories(${INCLUDE_DIRS} /opt/pyenv/versions/3.7.13/include/python3.7m/)
    LINK_DIRECTORIES(${LINK_DIRS} /opt/pyenv/versions/3.7.13/lib/)
    
    file( GLOB main_file_list ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) 
    file( GLOB source_files ${CMAKE_CURRENT_SOURCE_DIR}/*.cc)
    
    foreach( main_file ${main_file_list} )
        file(RELATIVE_PATH filename ${CMAKE_CURRENT_SOURCE_DIR} ${main_file})
        string(REPLACE ".cpp" "" file ${filename})
        add_executable(${file}  ${main_file} ${source_files})
        target_link_libraries(${file} ${CONAN_LIBS} pthread python3.7m)
    endforeach( main_file ${main_file_list})
    

    conanfile.txt
    本例使用了boost/algorithm/string.hpp中的相关算法,来简化我们的字符串操作,所以需要安装boost依赖。nlohmannn_json库不需要[可选]

    [requires]
    nlohmann_json/3.11.3
    boost/1.72.0
    
    [generators]
    cmake
    

    相关代码,
    consts.h

    #ifndef _FREDRIC_CONST_H_
    #define _FREDRIC_CONST_H_
    
    #include <string>
    extern std::string PointTemp;   
    
    #endif
    

    consts.cc

    #include "consts.h"
    
    std::string PointTemp = R"("p{0}": { "x": {1}, "y": {2}},)";
    

    point.h

    #ifndef _FREDRIC_POINT_H_
    #define _FREDRIC_POINT_H_
    
    struct point_t {
        float x;
        float y;
    };
    
    struct parking_lot_t {
        point_t p0;
        point_t p1;
        point_t p2;
        point_t p3;
    };
    #endif
    

    matplotlibcpp.h 请从这里下载
    https://github.com/lava/matplotlib-cpp/tree/master
    main.cpp

    #include <iostream>
    #include <sstream>
    
    #include "point.h"
    #include "consts.h"
    #include <vector>
    #include <boost/algorithm/string.hpp>
    
    #define WITHOUT_NUMPY
    #include "matplotlibcpp.h"
    
    namespace plt = matplotlibcpp;
    
    enum ps_type_t {
        TWO_VERTICALS,
        TWO_VERTICALS_STEPPED,
        VERTICAL_AND_HORIZONTAL,
        MULTI_VERTICALS_STEPPED
    };
    
    struct parking_lot_maker_t {
        std::vector<parking_lot_t> two_verticals() {
            std::vector<parking_lot_t> results;
            point_t p0 {4, -2.2};
            point_t p1 {4, -2.2 - 5.5};
            point_t p2 {4 + 2.4, -2.2 - 5.5};
            point_t p3 {4 + 2.4, -2.2};
            parking_lot_t vert {p0, p1, p2, p3};
    
            point_t h_p0 {p3.x + 0.3 + 5.5, p3.y};
            point_t h_p1 {p3.x + 0.3, p3.y};
            point_t h_p2 {h_p1.x, h_p1.y - 2.4};
            point_t h_p3 {h_p2.x + 5.5, h_p2.y};
    
            parking_lot_t hori {h_p0, h_p1, h_p2, h_p3};
            results.push_back(vert);
            results.push_back(hori);
            return results;
        }
        
        std::vector<parking_lot_t> two_verticals_stepped() {
            std::vector<parking_lot_t> results;
            point_t p0 {4, -2.2};
            point_t p1 {4, -2.2 - 5.5};
            point_t p2 {4 + 2.4, -2.2 - 5.5};
            point_t p3 {4 + 2.4, -2.2};
            parking_lot_t vert {p0, p1, p2, p3};
    
            point_t h_p0 {p3.x + 0.3 + 5.5, p3.y+0.4};
            point_t h_p1 {p3.x + 0.3, h_p0.y};
            point_t h_p2 {h_p1.x, h_p1.y - 2.4 + 0.4};
            point_t h_p3 {h_p2.x + 5.5, h_p2.y};
    
            parking_lot_t hori {h_p0, h_p1, h_p2, h_p3};
            results.push_back(vert);
            results.push_back(hori);
            return results;
        }
    
        std::vector<parking_lot_t> vertical_and_horizontal() {
            std::vector<parking_lot_t> results;
            point_t p0 {4, -2.2};
            point_t p1 {4, -2.2 - 5.5};
            point_t p2 {4 + 2.4, -2.2 - 5.5};
            point_t p3 {4 + 2.4, -2.2};
            parking_lot_t vert {p0, p1, p2, p3};
    
            point_t v_p0 {p3.x + 0.3, p3.y};
            point_t v_p1 {v_p0.x, v_p0.y - 2.4};
            point_t v_p2 {v_p1.x + 5.5, v_p1.y};
            point_t v_p3 {v_p2.x, v_p2.y + 2.4};
    
            parking_lot_t vert1 {v_p0, v_p1, v_p2, v_p3};
            results.push_back(vert);
            results.push_back(vert1);
            return results;
        }
        
        std::vector<parking_lot_t> multi_verticals_stepped() {
            std::vector<parking_lot_t> results;
            point_t p0 {4, -2.2};
            point_t p1 {4, -2.2 - 5.5};
            point_t p2 {4 + 2.4, -2.2 - 5.5};
            point_t p3 {4 + 2.4, -2.2};
            parking_lot_t vert {p0, p1, p2, p3};
            results.push_back(vert);
            for(std::size_t i=1; i<=3; ++i) {
                parking_lot_t vert1 {{p0.x + i*(0.3 + 2.4), p0.y + i* 0.4}, {p1.x + i*(0.3 + 2.4), p1.y + i* 0.4},
                    {p2.x +i*(0.3 + 2.4), p2.y + i * 0.4}, {p3.x + i*(0.3 + 2.4), p3.y + i* 0.4}};
                results.push_back(vert1);
            }
            return results;
        }
    
        void print_a_plot(parking_lot_t const& ps) {
            std::string replaced_0_str = boost::algorithm::replace_all_copy(PointTemp, "{0}", "0");
            boost::algorithm::replace_all(replaced_0_str, "{1}", std::to_string(ps.p0.x));
            boost::algorithm::replace_all(replaced_0_str, "{2}", std::to_string(ps.p0.y));
    
            std::string replaced_1_str = boost::algorithm::replace_all_copy(PointTemp, "{0}", "1");
            boost::algorithm::replace_all(replaced_1_str, "{1}", std::to_string(ps.p1.x));
            boost::algorithm::replace_all(replaced_1_str, "{2}", std::to_string(ps.p1.y));
            
            std::string replaced_2_str = boost::algorithm::replace_all_copy(PointTemp, "{0}", "2");
            boost::algorithm::replace_all(replaced_2_str, "{1}", std::to_string(ps.p2.x));
            boost::algorithm::replace_all(replaced_2_str, "{2}", std::to_string(ps.p2.y));
                
            std::string replaced_3_str = boost::algorithm::replace_all_copy(PointTemp, "{0}", "3");
            boost::algorithm::replace_all(replaced_3_str, "{1}", std::to_string(ps.p3.x));
            boost::algorithm::replace_all(replaced_3_str, "{2}", std::to_string(ps.p3.y));
            std::cout << replaced_0_str << replaced_1_str << replaced_2_str << replaced_3_str << std::endl;
        }
    
        void plot_and_save_plot_file(parking_lot_t const& ps) {
            std::vector<float> x_values;
            std::vector<float> y_values;
            x_values.push_back(ps.p0.x); x_values.push_back(ps.p1.x);
            x_values.push_back(ps.p2.x); x_values.push_back(ps.p3.x);
    
            y_values.push_back(ps.p0.y); y_values.push_back(ps.p1.y);
            y_values.push_back(ps.p2.y); y_values.push_back(ps.p3.y);
            plt::scatter(x_values, y_values, 50.0);
        }
        
        void save_results(std::string const& title, std::vector<parking_lot_t> const& results) {
            plt::clf();
            std::cout << title << "========" << std::endl;
            for(auto const& ps: results) {
               print_a_plot(ps);
               plot_and_save_plot_file(ps);
            }
    
            std::stringstream result_ss;
            result_ss << title << ".png";
            plt::save(result_ss.str());
            std::cout << title << "========" << std::endl;
            std::cout << std::endl;
        } 
    
        void operator()(ps_type_t type_) {
            switch (type_) {
            case TWO_VERTICALS:{
                auto res = two_verticals();
                save_results("Two verticals", res);
            }
                break;
            case TWO_VERTICALS_STEPPED:{
                auto res = two_verticals_stepped();
                save_results("Two verticals stepped", res);
            }
                break;
    
            case VERTICAL_AND_HORIZONTAL: {
                auto res = vertical_and_horizontal();
                save_results("Vertical and horizontal", res);
            }
                break;
            case MULTI_VERTICALS_STEPPED: {
                auto res = multi_verticals_stepped();
                save_results("Multi verticals stepped", res);
            }
            
            default:
                break;
            }
        }
    };
    
    
    int main(int argc, char* argv[]) {
        parking_lot_maker_t p_lot_maker;
        p_lot_maker(ps_type_t::TWO_VERTICALS);
        p_lot_maker(ps_type_t::TWO_VERTICALS_STEPPED);
        p_lot_maker(ps_type_t::VERTICAL_AND_HORIZONTAL);
        p_lot_maker(ps_type_t::MULTI_VERTICALS_STEPPED);
    
        return EXIT_SUCCESS;
    }
    

    程序输出如下


    image.png image.png

    相关文章

      网友评论

          本文标题:C++ 使用matplotlib绘图

          本文链接:https://www.haomeiwen.com/subject/foyfxjtx.html