C++ 使用matplotlib绘图

众所周知,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
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容