#pragma once #include <vtkPolyData.h> #include <vtkSmartPointer.h> #include <vtkTexture.h> #include <vtkImageData.h>
//! @brief 指定サイズの矩形を作成 //! @note テクスチャ座標設定済み //! @param width 幅(ピクセル) //! @param height 高さ(ピクセル) //! @return 矩形ポリゴンのvtkPolyData vtkSmartPointer<vtkPolyData> MakeScreenAlignedQuad(float width, float height);
//! @brief 矩形ポリゴンのサイズを変更 //! @param quad 矩形ポリゴンのvtkPolyData //! @param newWidth 新しい幅(ピクセル) //! @param newHeight 新しい高さ(ピクセル) //! @return なし void ResizeQuad(vtkPolyData* quad, float newWidth, float newHeight);
//! @brief vtkTextureにvtkImageDataをセット //! @param texture テクスチャオブジェクト //! @param image 画像データオブジェクト //! @return なし void SetTextureImage(vtkTexture* texture, vtkImageData* image);
//! @brief 画像配列から vtkImageData を生成 //! @param pixels 画像ピクセル配列(RGBAまたはRGB) //! @param width 画像幅(ピクセル) //! @param height 画像高さ(ピクセル) //! @param numComponents ピクセルあたりの成分数(3または4) vtkSmartPointer<vtkImageData> MakeImageDataFromBuffer( const unsigned char* pixels, int width, int height, int numComponents );
#include "MyTexture.hpp" #include <vtkFloatArray.h> #include <vtkPointData.h>
vtkSmartPointer<vtkPolyData> MakeScreenAlignedQuad(float width, float height) { vtkNew<vtkPoints> pts; pts->SetNumberOfPoints(4); pts->SetPoint(0, 0.0, 0.0, 0.0); pts->SetPoint(1, width, 0.0, 0.0); pts->SetPoint(2, width, height, 0.0); pts->SetPoint(3, 0.0, height, 0.0); vtkNew<vtkCellArray> polys; vtkIdType ids[4] = { 0,1,2,3 }; polys->InsertNextCell(4, ids); vtkNew<vtkFloatArray> tcoords; tcoords->SetName("TCoords"); tcoords->SetNumberOfComponents(2); tcoords->InsertNextTuple2(0.f, 0.f); // 左下 tcoords->InsertNextTuple2(1.f, 0.f); // 右下 tcoords->InsertNextTuple2(1.f, 1.f); // 右上 tcoords->InsertNextTuple2(0.f, 1.f); // 左上 vtkNew<vtkPolyData> pd; pd->SetPoints(pts); pd->SetPolys(polys); pd->GetPointData()->SetTCoords(tcoords); return pd; }
vtkSmartPointer<vtkImageData> MakeImageDataFromBuffer( const unsigned char* pixels, int width, int height, int numComponents ) { vtkNew<vtkImageData> img; img->SetDimensions(width, height, 1); img->AllocateScalars(VTK_UNSIGNED_CHAR, numComponents); const int stride = numComponents; auto* dst = static_cast<unsigned char*>(img->GetScalarPointer()); std::memcpy(dst, pixels, static_cast<size_t>(width) * height * stride); return img; }
void ResizeQuad(vtkPolyData* quad, float newWidth, float newHeight) { auto* pts = quad->GetPoints(); pts->SetPoint(0, 0.0, 0.0, 0.0); pts->SetPoint(1, newWidth, 0.0, 0.0); pts->SetPoint(2, newWidth, newHeight, 0.0); pts->SetPoint(3, 0.0, newHeight, 0.0); pts->Modified(); quad->Modified(); }
void SetTextureImage(vtkTexture* texture, vtkImageData* image) { texture->SetInputData(image); texture->InterpolateOn(); // バイリニア補間 texture->RepeatOff(); // 画像外は伸ばさない texture->EdgeClampOn(); texture->Modified(); }
// 画像生成 std::vector<unsigned char> MakeCheckerRGBA(int w, int h, int block = 16) { std::vector<unsigned char> buf(static_cast<size_t>(w) * h * 4); for (int y = 0; y < h; ++y) { for (int x = 0; x < w; ++x) { bool on = ((x / block) + (y / block)) % 2 == 0; unsigned char c = on ? 230 : 60; size_t idx = (static_cast<size_t>(y) * w + x) * 4; buf[idx + 0] = c; buf[idx + 1] = c; buf[idx + 2] = c; buf[idx + 3] = 255; } } return buf; }
// テクスチャオブジェクト作成 /////////////// vtkNew<vtkTexture> texture; // 画像データ作成 /////////////////////////// std::vector<unsigned char> pixels = MakeCheckerRGBA(256, 256, 32); // 画像データをvtkImageDataに変換 /////////// vtkSmartPointer<vtkImageData> imgdata = MakeImageDataFromBuffer(pixels.data(), 256, 256, 4); // テクスチャに画像データをセット /////////// SetTextureImage(texture, imgdata); // ポリゴン作成 ///////////////////////////// auto poly_quad = MakeScreenAlignedQuad(100, 200); vtkNew<vtkPolyDataMapper> mapper; mapper->SetInputData(poly_quad); vtkNew<vtkActor> actor; actor->SetMapper(mapper); actor->SetTexture(texture); auto renderer = vtkSmartPointer<vtkRenderer>::New(); renderer->AddActor(actor);

Win32APIからCEFを使用するコードを書きたかったので前に書いたものを整頓した。
実行には.exeファイルと同じ場所
cef_binary_138.0.15+gd0f1f64+chromium-138.0.7204.50_windows64\Resources\
の内容(localesフォルダなど)をコピーする。
#include "MyCEFControl.hpp" #include <Windows.h> #include <windowsx.h>
void OnPaint(HWND hwnd, HDC hdc) { MyHandler* handler = (MyHandler*)GetWindowLongPtr(hwnd, GWLP_USERDATA); if (handler) { CefRefPtr<CefRenderHandler> baseRenderHandler = handler->GetRenderHandler(); MyRenderHandler* renderHandler = static_cast<MyRenderHandler*>(baseRenderHandler.get()); RGBAImage img = renderHandler->m_browserImage; if (img.buffer.size() > 0) { // ビットマップ情報の設定 BITMAPINFO bmi; ZeroMemory(&bmi, sizeof(BITMAPINFO)); bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biWidth = img.width; bmi.bmiHeader.biHeight = -img.height; // 上下反転 bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = 24; // RGB24ビット bmi.bmiHeader.biCompression = BI_RGB; // 画像データを描画 SetDIBitsToDevice( hdc, 0, 0, // 描画位置 img.width, img.height, // 描画サイズ 0, 0, // ソースの開始位置 0, img.height, // ソースの開始ラインとライン数 img.buffer.data(), // ピクセルデータ &bmi, DIB_RGB_COLORS // カラーテーブルの使用方法 ); } } }
void OnMouseMove(HWND hwnd, int x, int y) { MyHandler* handler = (MyHandler*)GetWindowLongPtr(hwnd, GWLP_USERDATA); if (handler) { CefMouseEvent mouse_event; mouse_event.x = x; mouse_event.y = y; mouse_event.modifiers = 0; handler->GetBrowser()->GetHost()->SendMouseMoveEvent(mouse_event, false); InvalidateRect(hwnd, NULL, FALSE); } }
void OnLButtonDown(HWND hwnd, int x, int y) { MyHandler* handler = (MyHandler*)GetWindowLongPtr(hwnd, GWLP_USERDATA); if (handler) { CefMouseEvent mouse_event; mouse_event.x = x; mouse_event.y = y; mouse_event.modifiers = 0; handler->GetBrowser()->GetHost()->SendMouseClickEvent(mouse_event, cef_mouse_button_type_t::MBT_LEFT, false, 1); InvalidateRect(hwnd, NULL, FALSE); } }
void OnLButtonUp(HWND hwnd, int x, int y) { MyHandler* handler = (MyHandler*)GetWindowLongPtr(hwnd, GWLP_USERDATA); if (handler) { CefMouseEvent mouse_event; mouse_event.x = x; mouse_event.y = y; mouse_event.modifiers = 0; handler->GetBrowser()->GetHost()->SendMouseClickEvent(mouse_event, cef_mouse_button_type_t::MBT_LEFT, true, 1); InvalidateRect(hwnd, NULL, FALSE); } }
void OnClose(HWND hwnd) { MyHandler* handler = (MyHandler*)GetWindowLongPtr(hwnd, GWLP_USERDATA); if (handler) { handler->CloseAllBrowsers(true); } }
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) { MyHandler* handler = nullptr; LPCREATESTRUCT pcs; PAINTSTRUCT ps; HDC hdc; switch (msg) { case WM_CLOSE: OnClose(hwnd); DestroyWindow(hwnd); return 0; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); OnPaint(hwnd, hdc); EndPaint(hwnd, &ps); return 0; case WM_CREATE: return 0; case WM_DESTROY: //CefQuitMessageLoop(); PostQuitMessage(0); return 0; case WM_MOUSEMOVE: OnMouseMove(hwnd, GET_X_LPARAM(lp), GET_Y_LPARAM(lp)); return 0; case WM_LBUTTONDOWN: OnLButtonDown(hwnd, GET_X_LPARAM(lp), GET_Y_LPARAM(lp)); return 0; case WM_LBUTTONUP: OnLButtonUp(hwnd, GET_X_LPARAM(lp), GET_Y_LPARAM(lp)); return 0; } return DefWindowProc(hwnd, msg, wp, lp); }
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { HWND hwnd; MSG msg; WNDCLASS winc; winc.style = CS_HREDRAW | CS_VREDRAW; winc.lpfnWndProc = WndProc; winc.cbClsExtra = winc.cbWndExtra = 0; winc.hInstance = hInstance; winc.hIcon = LoadIcon(NULL, IDI_APPLICATION); winc.hCursor = LoadCursor(NULL, IDC_ARROW); winc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); winc.lpszMenuName = NULL; winc.lpszClassName = TEXT("SZL-WND"); if (!RegisterClass(&winc)) return -1; ///////////////////////////////////////////////////////////////////////// CefRefPtr<MyHandler> g_handler = MyInitCEF(hInstance); if (!g_handler) { return -1; } ///////////////////////////////////////////////////////////////////////// hwnd = CreateWindow( TEXT("SZL-WND"), TEXT("CEF test"), WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 500, 500, NULL, NULL, hInstance, nullptr ); if (hwnd == NULL) return -1; ///////////////////////////////////////////////////////////////////////// SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)(g_handler.get())); ///////////////////////////////////////////////////////////////////////// MyRenderSetting(hwnd,g_handler); ///////////////////////////////////////////////////////////////////////// // メッセージループ CefRunMessageLoop(); // CEFのシャットダウン CefShutdown(); return 0; }
#pragma once #include <include/cef_app.h> struct RGBAImage { int width; int height; std::vector<unsigned char> buffer; // RGBAの生データ }; RGBAImage FromRGBA(const unsigned char* rgba_buffer, int width, int height); class MyRenderHandler : public CefRenderHandler { public: HWND m_pCanvasWindow = nullptr; RGBAImage m_browserImage; // GetViewRect() をoverrideする // 必須:ビューポートのサイズを返す void GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) override; // 必須:レンダリング結果がここに来る void OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type, const RectList& dirtyRects, const void* buffer, int width, int height) override; // サイズを外から設定 void SetSize(int w, int h); private: IMPLEMENT_REFCOUNTING(MyRenderHandler); }; class MyHandler : public CefClient, public CefLifeSpanHandler { CefRefPtr<CefRenderHandler> renderHandler_; public: MyHandler(CefRefPtr<CefRenderHandler> renderHandler) : renderHandler_(renderHandler) { } CefRefPtr<CefRenderHandler> GetRenderHandler() override; CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override; void OnAfterCreated(CefRefPtr<CefBrowser> browser) override; void OnBeforeClose(CefRefPtr<CefBrowser> browser) override; void CloseAllBrowsers(bool force_close); CefRefPtr<CefBrowser> GetBrowser(); IMPLEMENT_REFCOUNTING(MyHandler); private: CefRefPtr<CefBrowser> m_Browser; }; CefRefPtr<MyHandler> MyInitCEF(HINSTANCE hInstance); void MyRenderSetting(HWND window, CefRefPtr<MyHandler> ghandler);
#include "MyCEFControl.hpp" void MyRenderHandler::GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect){ // ビューポートのサイズを返す rect = CefRect(0, 0, m_browserImage.width, m_browserImage.height); } // 必須:レンダリング結果がここに来る void MyRenderHandler::OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type, const RectList& dirtyRects, const void* buffer, int width, int height) { // ※ buffer は 32bit BGRA フォーマット m_browserImage = FromRGBA(static_cast<const unsigned char*>(buffer), width, height); InvalidateRect(m_pCanvasWindow, NULL, FALSE); } // サイズを外から設定 void MyRenderHandler::SetSize(int w, int h) { m_browserImage.buffer.resize(w * h * 4); m_browserImage.width = w; m_browserImage.height = h; } //============================================================= CefRefPtr<CefRenderHandler> MyHandler::GetRenderHandler() { return renderHandler_; } CefRefPtr<CefLifeSpanHandler> MyHandler::GetLifeSpanHandler() { return this; } void MyHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) { m_Browser = browser; } void MyHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser) { m_Browser = nullptr; CefQuitMessageLoop(); } void MyHandler::CloseAllBrowsers(bool force_close) { if (m_Browser) { m_Browser->GetHost()->CloseBrowser(force_close); } } CefRefPtr<CefBrowser> MyHandler::GetBrowser() { return m_Browser; } //============================================================= RGBAImage FromRGBA(const unsigned char* rgba_buffer, int width, int height) { // wxImage用にRGBを抜き出す // 既存の生配列からstd::vectorへの変換例 std::vector<unsigned char> rgb_data(rgba_buffer, rgba_buffer + width * height * 3); for (int i = 0; i < width * height; ++i) { rgb_data[i * 3 + 0] = rgba_buffer[i * 4 + 0]; rgb_data[i * 3 + 1] = rgba_buffer[i * 4 + 1]; rgb_data[i * 3 + 2] = rgba_buffer[i * 4 + 2]; } RGBAImage img; img.width = width; img.height = height; img.buffer = std::move(rgb_data); return img; } CefRefPtr<MyHandler> MyInitCEF(HINSTANCE hInstance) { CefMainArgs main_args(hInstance); int exit_code = CefExecuteProcess(main_args, nullptr, nullptr); if (exit_code >= 0) return nullptr; // CEFの設定 CefSettings settings; settings.no_sandbox = true; // マルチスレッドメッセージループを無効にする // オフスクリーンレンダリングでは false必須 settings.multi_threaded_message_loop = false; CefInitialize(main_args, settings, nullptr, nullptr); ///////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// CefRefPtr<MyRenderHandler> renderHandler = new MyRenderHandler(); CefRefPtr<MyHandler> g_handler = CefRefPtr<MyHandler>(new MyHandler(renderHandler)); return g_handler; } void MyRenderSetting(HWND window, CefRefPtr<MyHandler> ghandler) { // MyRenderHandlerを取得 CefRefPtr<CefRenderHandler> baseRenderHandler = ghandler->GetRenderHandler(); CefRefPtr<MyRenderHandler> renderHandler = static_cast<MyRenderHandler*>(baseRenderHandler.get()); renderHandler->m_pCanvasWindow = window; renderHandler->SetSize(400, 400); // ビューポートのサイズを設定 CefBrowserSettings browser_settings; CefWindowInfo window_info; CefRect cefRect( 0, 0, 800, 600); // オフスクリーンレンダリング window_info.SetAsWindowless(nullptr); CefBrowserHost::CreateBrowser( window_info, ghandler, "https://www.google.com", browser_settings, nullptr, nullptr); }
actorなどの生成まではスレッドでできるが、Render()関数などの呼び出しはメインスレッドで行わなければいけない。
VTKのメッセージループを使う限りはシグナルを送ったりということが簡単にできないので、OnTimerで定期的にRender()をする。
#include <iostream> #include <thread> //VTK_MODULE_INITに必要 #include <vtkAutoInit.h> #include <vtkSmartPointer.h> #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> #include <vtkPolyDataMapper.h> #include <vtkSphereSource.h> #include <vtkCallbackCommand.h> #include <vtkCamera.h> #include <vtkActor.h> // #include "createpoly.hpp" //必須 VTK_MODULE_INIT(vtkRenderingOpenGL2); VTK_MODULE_INIT(vtkInteractionStyle);
// 定期的に Render する void OnTimer(vtkObject* /*caller*/, unsigned long /*eventId*/, void* clientData, void* /*callData*/) { auto renderWindow = static_cast<vtkRenderWindow*>(clientData); if (renderWindow) { renderWindow->Render(); } }
// 停止フラグ std::atomic<bool> g_stop{ false };
// スレッド void work(vtkSmartPointer<vtkRenderer> renderer) { for (size_t i = 0; i < 100; i++) { // 乱数 double x = (std::rand() % 100) / 10.0 - 5.0; double y = (std::rand() % 100) / 10.0 - 5.0; double z = (std::rand() % 100) / 10.0 - 5.0; // 球体 vtkSmartPointer<vtkSphereSource> sphereSource = vtkSmartPointer<vtkSphereSource>::New(); sphereSource->SetCenter(x,y,z); sphereSource->SetRadius(5.0); sphereSource->Update(); vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New(); vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); mapper->SetInputConnection(sphereSource->GetOutputPort()); actor->SetMapper(mapper); renderer->AddActor(actor); std::this_thread::sleep_for(std::chrono::seconds(1)); if(g_stop) break; } }
int main(int /*argc*/, char** /*argv*/) { auto renderer = vtkSmartPointer<vtkRenderer>::New(); renderer->ResetCamera(); renderer->GetActiveCamera()->SetPosition(0, 0, 100); ////////////////////////////////////// auto interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New(); ////////////////////////////////////// auto renderWindow = vtkSmartPointer<vtkRenderWindow>::New(); renderWindow->AddRenderer(renderer); renderWindow->SetInteractor(interactor); renderWindow->Render(); auto cb = vtkSmartPointer<vtkCallbackCommand>::New(); cb->SetClientData(renderWindow); cb->SetCallback(OnTimer); interactor->AddObserver(vtkCommand::TimerEvent, cb); interactor->Initialize(); interactor->CreateRepeatingTimer(10); std::thread t1(work, renderer); interactor->Start(); //イベントループへ入る g_stop = true; t1.join(); return 0; }
Group Outputの前に Realize Instancesを入れることで、モディファイアの設定からapplyができるようになる。

結果が全て一つのオブジェクトになっているので、個別のオブジェクトにするには By Loose Parts で分離する。
Mesh → Separate → By Loose Parts

ただし、 By Loose Partsは頂点が繋がっていなければ纏まってくれないので、連続していないパーツが一つのオブジェクトになっている場合はどこかでつなげておかないといけない

諸事情によりPythonで株価を取得するコードを書いた。
株価を取得するAPIは有料から無料までいろいろあるが今回はただ呼び出せば使える yfinance をつかう。
################################### # 株価取得 ################################### import yfinance as yf df = yf.download("AAPL", start="2020-01-01", interval="1d") ################################### # 終値をグラフ表示 ################################### import matplotlib.pyplot as plt df["Close"].plot(title="AAPL Closing Price") plt.show()

import yfinance as yf import matplotlib.pyplot as plt # データ取得 df = yf.download("AAPL", start="2020-01-01", interval="1d") # EMA(指数移動平均)を計算 df["EMA20"] = df["Close"].ewm(span=20, adjust=False).mean() # 20日EMA df["EMA50"] = df["Close"].ewm(span=50, adjust=False).mean() # 50日EMA # 終値とEMAを同じグラフに描画 plt.figure(figsize=(10, 5)) plt.plot(df.index, df["Close"], label="Close", color="black", linewidth=1) plt.plot(df.index, df["EMA20"], label="EMA 20", color="blue", linewidth=1) plt.plot(df.index, df["EMA50"], label="EMA 50", color="red", linewidth=1) plt.title("AAPL Closing Price with EMA(20) & EMA(50)") plt.xlabel("Date") plt.ylabel("Price (USD)") plt.legend() plt.grid(True) plt.tight_layout() plt.show()

日本株は銘柄の後に.Tをつけるといいらしい。
import yfinance as yf import matplotlib.pyplot as plt tickers = ["7203.T", "6758.T", "7974.T"] # 一括取得 df = yf.download(tickers, start="2020-01-01", interval="1d")["Close"] # DataFrame の確認 print(df.head()) print("==========================") # 銘柄 for symbol in df.columns: print(df[symbol]) print("==========================") # グラフ描画 plt.figure(figsize=(10, 5)) for symbol in df.columns: plt.plot( df.index, # 横軸 日付 df[symbol], # 縦軸 価格 label=symbol # 凡例のラベル ) print("==========================") plt.title("Stock Prices (Close)") plt.xlabel("Date") plt.ylabel("Price (JPY)") plt.legend() plt.grid(True) plt.tight_layout() plt.show()

.vtkhdf形式は複数のオブジェクトを一つのファイルにまとめて保存できる。
ただしバイナリ形式なのと、保存形式が複数あるのでややこしい。今回はvtkMultiBlockDataSet形式で保存する。
vtkhdfで保存・読み込みを行う。データはvtkMultiBlockDataSetで保存する
#pragma once #include "createpoly.hpp" #include <vtkDataArraySelection.h> ///////////////////////////////////////// ///////////////////////////////////////// // 保存コード ///////////////////////////////////////// /////////////////////////////////////////
void save_as_Multiblock() { vtkSmartPointer<vtkPolyData> polypoints = createPoints(); vtkSmartPointer<vtkPolyData> polycone = createCone(); vtkSmartPointer<vtkPolyData> polyline = createPolyLine(); auto mb = vtkSmartPointer<vtkMultiBlockDataSet>::New(); mb->SetNumberOfBlocks(3); mb->SetBlock(0, polypoints); mb->SetBlock(1, polycone); mb->SetBlock(2, polyline); auto w = vtkSmartPointer<vtkHDFWriter>::New(); w->SetInputData(mb); w->SetFileName("scene.vtkhdf"); w->Write(); }
/////////////////////////////////////////
/////////////////////////////////////////
// 読み込みコード
/////////////////////////////////////////
/////////////////////////////////////////
std::vector< vtkSmartPointer<vtkPolyData> > load_as_Multiblock() { std::vector< vtkSmartPointer<vtkPolyData> > polyvec; auto reader = vtkSmartPointer<vtkHDFReader>::New(); reader->SetFileName("scene.vtkhdf"); reader->GetPointDataArraySelection()->EnableAllArrays(); reader->GetCellDataArraySelection()->EnableAllArrays(); reader->Update(); //vtkDataObject* out = reader->GetOutput(); vtkDataObject* out = reader->GetOutputDataObject(0); auto mb = vtkMultiBlockDataSet::SafeDownCast(out); std::cout << "MultiBlock with " << mb->GetNumberOfBlocks() << " blocks\n"; // 各ブロックを処理 for (unsigned int i = 0; i < mb->GetNumberOfBlocks(); i++) { vtkPolyData* poly = vtkPolyData::SafeDownCast(mb->GetBlock(i)); if (poly) { // RGB配列があればアクティブにする例 if (poly->GetPointData()->HasArray("RGB")) { poly->GetPointData()->SetActiveScalars("RGB"); } } polyvec.push_back(poly); } return polyvec; }
データを作成する。
#pragma once #include <vtkSmartPointer.h> #include <vtkDoubleArray.h> #include <vtkPointData.h> #include <vtkConeSource.h> #include <vtkCellArray.h> #include <vtkPoints.h> #include <vtkPolyData.h> #include <vtkPolyDataMapper.h> #include <vtkProperty.h> #include <vtkUnsignedCharArray.h> #include <array> #include <vtkCellData.h>
vtkSmartPointer<vtkPolyData> createPoints() { // 頂点配列 vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New(); // 色情報の配列 vtkSmartPointer<vtkUnsignedCharArray> colors = vtkSmartPointer<vtkUnsignedCharArray>::New(); colors->SetNumberOfComponents(3); colors->SetName("RGB"); // 頂点インデクスの配列 vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New(); for (size_t i = 0; i < 100000; i++) { double x = (double)rand() / (double)RAND_MAX; double y = (double)rand() / (double)RAND_MAX; double z = (double)rand() / (double)RAND_MAX; points->InsertNextPoint(x, y, z); // 座標追加 unsigned char r = static_cast<unsigned char>(x * 255.0); unsigned char g = static_cast<unsigned char>(y * 255.0); unsigned char b = static_cast<unsigned char>(z * 255.0); colors->InsertNextTypedTuple(std::array<unsigned char, 3>{r, g, b}.data()); cells->InsertNextCell(1); // 要素数 cells->InsertCellPoint(i); // 頂点インデックスを追加 } // --- vtkPolyData作成 --- auto polydata = vtkSmartPointer<vtkPolyData>::New(); polydata->SetPoints(points); polydata->SetVerts(cells); polydata->GetPointData()->SetScalars(colors); polydata->GetPointData()->SetActiveScalars("RGB"); return polydata; }
vtkSmartPointer<vtkPolyData> createCone() { vtkSmartPointer<vtkConeSource> coneSource; coneSource = vtkSmartPointer<vtkConeSource>::New(); coneSource->SetHeight(1.0); coneSource->SetRadius(0.2); coneSource->SetResolution(10); coneSource->Update(); vtkSmartPointer<vtkPolyData> conePolyData = coneSource->GetOutput(); return conePolyData; }
vtkSmartPointer<vtkPolyData> createPolyLine() { // VTKのデータ構造で W の形状を作成 // 頂点配列 vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New(); // 色情報の配列 vtkSmartPointer<vtkUnsignedCharArray> colors = vtkSmartPointer<vtkUnsignedCharArray>::New(); colors->SetNumberOfComponents(3); colors->SetName("RGB"); // 頂点インデクスの配列 vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New(); // 頂点追加 points->InsertNextPoint(0.0, 0.0, 0.0); // 0 colors->InsertNextTypedTuple(std::array<unsigned char, 3>{255,0,0}.data()); points->InsertNextPoint(0.5, 1.0, 0.0); // 1 colors->InsertNextTypedTuple(std::array<unsigned char, 3>{0,255, 0}.data()); points->InsertNextPoint(1.0, 0.0, 0.0); // 2 colors->InsertNextTuple3(0.0, 0.0, 1.0); colors->InsertNextTypedTuple(std::array<unsigned char, 3>{0, 0, 255}.data()); points->InsertNextPoint(1.5, 1.0, 0.0); // 3 colors->InsertNextTypedTuple(std::array<unsigned char, 3>{255, 255, 0}.data()); points->InsertNextPoint(2.0, 0.0, 0.0); // 4 colors->InsertNextTypedTuple(std::array<unsigned char, 3>{255, 0, 255}.data()); // 頂点インデクス追加 cells->InsertNextCell(5); // 要素数 cells->InsertCellPoint(0); cells->InsertCellPoint(1); cells->InsertCellPoint(2); cells->InsertCellPoint(3); cells->InsertCellPoint(4); // --- vtkPolyData作成 --- auto polydata = vtkSmartPointer<vtkPolyData>::New(); polydata->SetPoints(points); polydata->SetLines(cells); polydata->GetPointData()->SetScalars(colors); return polydata; }
#pragma once #include <vtkCellArray.h> #include <vtkPoints.h> #include <vtkPolyData.h> #include <vtkPolyDataMapper.h> #include <vtkActor.h> #include <vtkDoubleArray.h> #include <vtkSmartPointer.h> #include <vtkPointData.h> #include <vtkProperty.h> #include <vtkLine.h> #include "vtkFromO3dCommon.hpp" #include <open3d/Open3D.h> namespace vtko3d {
vtkSmartPointer<vtkPolyData> toLineSetPolyData(const open3d::geometry::LineSet& linesegments, USEVALUE usedata) { // 頂点の作成 vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New(); // 色情報の配列 vtkSmartPointer<vtkDoubleArray> colors = vtkSmartPointer<vtkDoubleArray>::New(); colors->SetNumberOfComponents(3); colors->SetName("Colors"); for (size_t i = 0; i < linesegments.points_.size(); i++) { double x = linesegments.points_[i].x(); double y = linesegments.points_[i].y(); double z = linesegments.points_[i].z(); points->InsertNextPoint(x, y, z); if (usedata & POINT_RGB) { double r = linesegments.colors_[i].x(); double g = linesegments.colors_[i].y(); double b = linesegments.colors_[i].z(); colors->InsertNextTuple3(r, g, b); // 色情報追加 } } // 線分(Cell)を定義 vtkSmartPointer<vtkCellArray> lines = vtkSmartPointer<vtkCellArray>::New(); for (size_t i = 0; i < linesegments.lines_.size(); i++) { size_t v1 = linesegments.lines_[i].x(); size_t v2 = linesegments.lines_[i].y(); // 線分を作成 auto line = vtkSmartPointer<vtkLine>::New(); line->GetPointIds()->SetId(0, v1); // 始点 line->GetPointIds()->SetId(1, v2); // 終点 lines->InsertNextCell(line); } // PolyDataへ格納 vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New(); polyData->SetPoints(points); polyData->SetLines(lines); polyData->GetPointData()->SetScalars(colors); return polyData; }
vtkSmartPointer<vtkActor> toLineSegmentsActor(vtkSmartPointer<vtkPolyDataMapper> mapper, std::optional< std::array<double, 3> > single_color = std::nullopt, int line_width = 1) { vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New(); actor->SetMapper(mapper); if (single_color.has_value()) { actor->GetProperty()->SetColor(single_color.value()[0], single_color.value()[1], single_color.value()[2]); } else { actor->GetProperty()->SetColor(1.0, 1.0, 1.0); // デフォルトは白色 } if (line_width > 0) { actor->GetProperty()->SetLineWidth(line_width); // 線の太さ } return actor; }
std::shared_ptr<open3d::geometry::LineSet> createSampleLineSegments() { auto linesets = std::make_shared<open3d::geometry::LineSet>(); for (size_t i = 0; i < 1000; i++) { for (size_t j = 0; j < 100; j++) { double x1 = (double)rand() / (double)RAND_MAX; double y1 = (double)rand() / (double)RAND_MAX; double z1 = 0.0;// (double)rand() / (double)RAND_MAX; double x2 = x1; double y2 = y1; double z2 = 1.0;// (double)rand() / (double)RAND_MAX; linesets->points_.emplace_back(x1, y1, z1); linesets->points_.emplace_back(x2, y2, z2); linesets->colors_.emplace_back(x1, y1, z1); // 赤色のライン linesets->colors_.emplace_back(x2, y2, z2); // 青色のライン linesets->lines_.emplace_back(i * 2, i * 2 + 1); // ラインセグメントのインデックス } } return linesets; }
}
auto linesegments = vtko3d::createSampleLineSegments(); auto polyData = vtko3d::toLineSetPolyData(*linesegments, vtko3d::POINT_RGB); auto mapper = vtko3d::toMapper(polyData); auto actor = vtko3d::toLineSegmentsActor(mapper, std::nullopt, 2);
