LoginSignup
5
5

More than 3 years have passed since last update.

ボロノイ図

Last updated at Posted at 2017-12-14

概要

こちらはC++ (DXライブラリ)を使って、ボロノイ図を作成する記事です。
以前、記事を書いた"~水彩ボロノイ図を線画~"とは違うアルゴリズムを使用しています。

DXライブラリはこちらからダウンロードできます。
何か不備がありましたら指摘していただければ幸いです。

コード

1/12秒おきにボロノイ図が自動分割生成されるプログラムです。
このコードでは、最大で100個まで分割します。

Main.cpp
#define NOMINMAX
#include "DxLib.h"
#include <vector>
#include <chrono>

//横画面サイズ
#define MAP_X 512

//縦画面サイズ
#define MAP_Y 512

//原点の最大個数
#define VORONOI_COUNT_MAX 1

struct Point {
    int x, y;
};

static int DistanceSqrd(const Point& point, int x, int y) {
    int xd = x - point.x;
    int yd = y - point.y;
    return (xd * xd) + (yd * yd);
}

class Voronoi {
public:
    //ボロノイ図を作る
    void Make(int count) {
        CreatePointColor(count);
        CreateSites();
        SetSitesPoints();
    }

private:
    std::vector<Point> points_;
    std::vector<unsigned int> colors_;

    //原点の場所と色を決定する
    void CreatePointColor(int count) {
        const int w = MAP_X - 20, h = MAP_Y - 20;
        unsigned int c;
        for (int i = 0; i < count; i++) {
            points_.push_back({ GetRand(w) + 10, GetRand(h) + 10 });
            c = GetColor(GetRand(100) + 150, GetRand(100) + 150, GetRand(100) + 150);
            colors_.push_back(c);
        }
    }

    //図形を線画
    void CreateSites() {
        int w = MAP_X, h = MAP_Y, d, ind, dist;
        for (int hh = 0; hh < h; hh++) {
            for (int ww = 0; ww < w; ww++) {
                ind = -1;
                dist = std::numeric_limits<int>::max();
                for (int it = 0; it < points_.size(); it++) {
                    const Point& p = points_[it];
                    d = DistanceSqrd(p, ww, hh);
                    if (d < dist) {
                        dist = d;
                        ind = it;
                    }
                }
                if (ind > -1) DrawPixel(ww, hh, colors_[ind]);
            }
        }
    }

    //原点を線画
    void SetSitesPoints() {
        for (const auto& point : points_) {
            int x = point.x, y = point.y;
            for (int i = -1; i < 2; i++)
                for (int j = -1; j < 2; j++)
                    DrawPixel(x + i, y + j, GetColor(0, 0, 0));
        }
    }
};

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {

    //log出力停止・ウィンドウモード変更・初期化・裏画面設定
    SetOutApplicationLogValidFlag(FALSE), ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen(DX_SCREEN_BACK);

    //画面サイズの決定
    SetGraphMode(MAP_X, MAP_Y, 32);

    //タイトル文字
    SetMainWindowText("Voronoi");

    //ボロノイ図を線画
    Voronoi diagram;

    //時間
    int time = 0;

    int voronoiCount = 0;

    //ボロノイ図を生成
    diagram.Make(1 + GetRand(VORONOI_COUNT_MAX - 1));

    while (ScreenFlip() == 0 && ProcessMessage() == 0) {
        //1/12秒おきにボロノイ図を生成
        if (time == 5 && voronoiCount < 100) {
            diagram.Make(1 + GetRand(VORONOI_COUNT_MAX - 1));
            time = 0;
            voronoiCount++;
        }

        //ESCキーで終了
        if (CheckHitKey(KEY_INPUT_ESCAPE)) break;

        //時間を増やす
        time++;
    }

    //DXライブラリの終了処理
    DxLib_End();
    return 0;
}

結果

実行してみたらこんな感じ

1513276802515.jpg

アニメーションしてみたらこんな感じ

circleanimationmuvie

ソースコードのライセンス

These codes are licensed under CC0.
CC0

ソースコードは自由に使用してください。

参考

DXライブラリ 関数リファレンスページ
新・C言語 ~ゲームプログラミングの館
ボロノイ図
ボロノイ図を作る
ボロノイ図とその3つの性質
ボロノイ分割とは?
GPUでボロノイ図を描画する
ボロノイ図の描画アルゴリズムについて
Voronoi diagram
vector

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5