boost-geometry-render

Boost.Geometry で遊ぶならやっぱり GUI でテストしたいよね!
って、ことで、glut を使用して、簡単な Boost.Geometry の描画用ライブラリをつくりました。
基本的に Boost.Geometry で描画するだけの事を考えているので、その他の事は特に何もしていません。
glut が使える環境なら多分動くんじゃないでしょうか。Windows しか試していませんが…。

[サンプルコード]

#include <cstdlib>
#include <gl/glut.h>
#include <gl/graphics.hpp>
#include <gl/geometry_render.hpp>
#include <boost/geometry/multi/geometries/multi_point.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/thread.hpp>

int
main(int argc, char* argv[]){
    namespace bg = boost::geometry;

    typedef bg::model::d2::point_xy<float> point_type;
    typedef bg::model::multi_point<point_type> multi_point_type;
    typedef bg::model::polygon<point_type> polygon_type;
    multi_point_type multi_point;
    
    // 適当な描画管理クラス
    // arc, argv, width, height
    gl::graphics g(argc, argv, 500, 500);
    
    // glutDisplayFunc にコールバック関数を登録
    // convex_hull の描画
    gl::displayfunc(g, [&](){
        namespace bg = boost::geometry;
        if(multi_point.empty())    return;
        
        // convex_hull の取得
        // multi_point からでは直接取得出来ないので、
        // 一旦 Polygon に変換してから取得を行う
        polygon_type tmp;
        bg::assign_points(tmp, multi_point);
        bg::model::polygon<point_type> hull;
        bg::convex_hull(tmp, hull);
        glColor3f(0.0f, 1.0f, 0.0f);
        // 取得した Polygon の描画
        gl::render(hull);
    });
    
    // multi_point の描画
    // 登録順に描画が行われる
    gl::displayfunc(g, [&](){
        // gl の描画設定
        glColor3f(1.0f, 0.0f, 0.0f);
        glPointSize(5.0f);
        // Geometry の描画
        gl::render(multi_point);
    });
    
    // マウスイベント
    gl::mousefunc(g, [&](int button, int state, int x, int y){
        // 左クリックが押された時のみ頂点を追加する
        if(button != GLUT_LEFT_BUTTON || state != GLUT_DOWN)    return;
        
        // クリックされたウィンドウ座標をスクリーン座標に変換して Geometry に追加
        multi_point.push_back(point_type(x / 250.0f - 1.0f, y / -250.0f + 1.0f));
    });
    
    // キー入力イベント
    gl::keyboardfunc(g, [](unsigned char key, int x, int y){
        if(key == 'q') return exit(0);
    });
    
    // idle
    gl::idlefunc(g, [&](){
        boost::this_thread::sleep(boost::posix_time::milliseconds(16));
        glutPostRedisplay();
    });
    
    // glut のメインループ
    g.run();
    
    return 0;
}

[出力画像]


こんな感じで、glut のコールバック関数を追加して使います。
glut のコールバック関数は関数ポインタしか受け取らなかったので、オブジェクトも受け取るようにラップしてあります。
(詳しくは、c_function.hpp とかでぐぐって下さい)
これで、Boost.PhoenixC++0xラムダ式とかが使い放題です。


ライブラリ側は基本的に gl に対して何もしていないので、座標系などはデフォルトのままです。
必要であれば、gl の関数を使用して、ユーザ側で設定する必要があります。


実装はまだ書きなぐりな状態なんですけど、サックリと使う分にはいいんじゃないでしょうか。
何かあれば、Twitter かコメントまでお願いします。
久々にAPIっぽいものを書いて楽しかった。

[注意]

凹ポリゴンに関しては、gl が対応していないので描画されません。
linestring 辺りに変換してなんとか頑張ってください。
あと Geometry の Container とかに依存している部分があるので、std::vector 以外だと動かないかも知れません。