Mugichoko's blog

Mugichoko’s blog

プログラミングを中心としたメモ書き.

ドロネー三角形分割:描画

目標

ランダムに生成した2次元点を入力として,ドロネー三角形分割を行い,結果を描画する.この際,以下の2つのライブラリを利用する. * OpenCVSubdiv2D * Fade2D

実装環境

OpenCV Subdiv2D

Visual Studioの設定

ググればすぐに有用な情報が見つかるので,他のサイトをご参照下さい.

プログラム

こちらを参考に実装した.

#include <iostream>
using namespace std;
#include <random>
#include <opencv2/opencv.hpp>

// Constants
const int PTS_NUM(100);
const int PTS_RANGE(600);
const string WND_NAME("Delaunay OpenCV Subdiv2D");

int main()
{
    // ----- Generate 2D points
    // Mersenne twister (random value generator)
    mt19937 mt;
    uniform_int_distribution<int> distribution(0, ::PTS_RANGE - 1);
    
    vector<cv::Point2f> pts;
    for (int i = 0; i < ::PTS_NUM; ++i)
    {
        int x = distribution(mt);
        int y = distribution(mt);
        pts.push_back(cv::Point2f(x, y));
    }

    // ----- Initialize Subdiv2D
    cv::Subdiv2D subdiv;
    subdiv.initDelaunay(cv::Rect(0, 0, ::PTS_RANGE, ::PTS_RANGE));
    subdiv.insert(pts);

    // ----- Draw Delaunay triangles
    cv::Mat img = cv::Mat::zeros(::PTS_RANGE, ::PTS_RANGE, CV_8UC3);

    // Draw points
    for (auto pt = pts.begin(); pt != pts.end(); ++pt)
    {
        cv::circle(img, *pt, 4, cv::Scalar(0, 0, 255), -1);
    }

    // Draw lines
    vector<cv::Vec6f> vDtTri;
    subdiv.getTriangleList(vDtTri);
    for (auto tri = vDtTri.begin(); tri != vDtTri.end(); ++tri)
    {
        cv::Vec6f &vec = *tri;
        cv::Point p1(vec[0], vec[1]);
        cv::Point p2(vec[2], vec[3]);
        cv::Point p3(vec[4], vec[5]);
        cv::line(img, p1, p2, cv::Scalar(64, 255, 128));
        cv::line(img, p2, p3, cv::Scalar(64, 255, 128));
        cv::line(img, p3, p1, cv::Scalar(64, 255, 128));
    }

    cv::namedWindow(::WND_NAME);
    cv::imshow(::WND_NAME, img);
    cv::waitKey();

    return 0;
}

実行結果

動いた!点を入力していないところにも線が伸びている… なぜだ?

f:id:Mugichoko:20170512111620j:plain

Fade2D

ダウンロードとインストー

  1. ここの中ほどにある「Getting started」内のリンクから「fadeRelease_v1.50.zip」をダウンロード
    • 「C:\Libraries\」に解凍したとする
    • 解凍したフォルダ名を「fadeRelease」から「Fade2D-1.5」に変更した
    • 以降,「C:\Libraries\Fade2D-1.5」を「Path」と呼ぶ
  2. 環境変数に「Path\x64」を設定し,PCを再起動

Visual Studioのプロジェクト作成

  1. Visual Studioを開いて「新しいプロジェクト」を作成
  2. 「インクルードディレクトリ」に以下を追加
    • Path\include_fade2d
  3. 「ライブラリディレクトリ」に以下を追加
    • Path\x64
  4. 「追加の依存ファイル」に必要なライブラリを追加
    • Debug設定: fade2D_x64_v140_Debug.lib
    • Release設定: fade2D_x64_v140_Release.lib

プログラム

「Path\examples_2D」にあるサンプルプログラムを参考に実装した.

#include <iostream>
using namespace std;
#include <random>
#include <Fade_2D.h>
namespace fade = GEOM_FADE2D;
#include <opencv2/opencv.hpp>

// Constants
const int PTS_NUM(100);
const int PTS_RANGE(600);
const string WND_NAME("Delaunay Fade 2D");


int main()
{
    // ----- Generate 2D points
    // Mersenne twister (random value generator)
    mt19937 mt;
    uniform_int_distribution<int> distribution(0, ::PTS_RANGE - 1);
    
    vector<fade::Point2> pts;
    for (int i = 0; i < ::PTS_NUM; ++i)
    {
        int x = distribution(mt);
        int y = distribution(mt);
        pts.push_back(fade::Point2(x, y));
    }

    // ----- Initialize Fade 2D
    fade::Fade_2D dt((unsigned int)pts.size());
    vector<fade::Point2 *> vDtVertPtr;
    dt.insert(pts, vDtVertPtr);

    // ----- Draw Delaunay triangles
    cv::Mat img = cv::Mat::zeros(::PTS_RANGE, ::PTS_RANGE, CV_8UC3);

    // Draw points
    for (auto pt = pts.begin(); pt != pts.end(); ++pt)
    {
        cv::circle(img, cv::Point(pt->x(), pt->y()), 4, cv::Scalar(0, 0, 255), -1);
    }

    // Draw lines
    vector<fade::Triangle2 *> vDtTri;
    dt.getTrianglePointers(vDtTri);
    for (auto tri = vDtTri.begin(); tri != vDtTri.end(); ++tri)
    {
        fade::Point2 *pt[3] = { (*tri)->getCorner(0), (*tri)->getCorner(1), (*tri)->getCorner(2) };
        cv::Point p1(pt[0]->x(), pt[0]->y());
        cv::Point p2(pt[1]->x(), pt[1]->y());
        cv::Point p3(pt[2]->x(), pt[2]->y());
        cv::line(img, p1, p2, cv::Scalar(64, 255, 128));
        cv::line(img, p2, p3, cv::Scalar(64, 255, 128));
        cv::line(img, p3, p1, cv::Scalar(64, 255, 128));
    }

    cv::namedWindow(::WND_NAME);
    cv::imshow(::WND_NAME, img);
    cv::waitKey();

    return 0;
}

実行結果

動いた!入力した点にだけ線が伸びている.

f:id:Mugichoko:20170512111617j:plain

以下は,昔に作った実時間デモの映像です.

www.youtube.com