本項から実際にデータを読み込んで値を保持するための処理を追加していきます。データ全体からだんだんと細かい値を読み込むように順番に追加していきます。
試しにSTLデータで作成したCgsTrianglesクラスにテキストファイルを1行読み込むメソッドを追加し、ブレイクポイントを使って正しく動作しているか確認してみましょう。
なお、テキストファイルのエンコードには様々な種類があり、エンコードによってファイルオープンの方法が異なりますが、提示された「house.stl」,「wheel3.stl」,「cone.stl」はいずれも BOM無しUTF-8 のファイルですので、ここでは BOM無しUTF-8 のみを対象とします。
CgsTriangles クラスの役割はファイルを開いて CTriangle にデータを読み込ませて三角形データを必要数だけため込むことです。
ファイル読み込みに必要なヘッダーファイルをインクルードしておきます。
【CgsTriangle.h】
#pragma once
#include <fstream>
#include <string>
#include <vector>
#include "CgsVector.h"
#include "CgsPoint.h"
1. ファイルパスを引数に渡してテキストファイルを読み込むメソッドを宣言します。
【CgsTriangle.h】
class CgsTriangles : public std::vector<CgsTriangle>
{
public:
bool ReadText(const std::wstring& path);
};
2. ファイルパスを引数に渡してテキストファイルを読み込むメソッドを定義します。
先ずはファイルを開いて閉じるだけの処理です。エンコード UTF-8 を指定してファイルを開きます。【補足:ロケール設定】
【CgsTriangle.cpp】
#include "pch.h"
#include "CgsTriangle.h"
bool CgsTriangles::ReadText(const std::wstring& path)
{
// 初期化
clear();
// ファイルを開く
FILE* fp = nullptr;
if (_wfopen_s(&fp, path.c_str(), L"rt, ccs=UTF-8")) {
return false;
}
std::wifstream ifs(fp);
if (!ifs.is_open()) {
return false;
}
// ファイルを閉じる
ifs.close();
return !empty();
}
3. STLテキストフォーマットでは先頭行に三角形データとは関係の無いデータを含んでいるので、先頭行を読み飛ばす処理を追加します。
念のため先頭行の文字列が "solid" で始まるかどうかを確認して不正な文字列ならばエラーとするようにしています。
【CgsTriangle.cpp】
bool CgsTriangles::ReadText(const std::wstring& path)
{
// 初期化
clear();
// ファイルを開く
FILE* fp = nullptr;
if (_wfopen_s(&fp, path.c_str(), L"rt, ccs=UTF-8")) {
return false;
}
std::wifstream ifs(fp);
if (!ifs.is_open()) {
return false;
}
// 任意文字列を含む先頭行の読み飛ばし
std::wstring str;
std::getline(ifs, str);
if (str.find(L"solid") != 0) {
return false;
}
// ファイルを閉じる
ifs.close();
return !empty();
}
[ファイル(F)]-[開く(O)...] メニューを選択し、ファイル選択ダイアログで STL ファイルを選択された後の処理を追加します。
【STLViewerDoc.cpp】
void CSTLViewerDoc::OnFileOpen()
{
// ファイル選択ダイアログ表示
CString strFilter;
const int length = strFilter.LoadString(IDS_FILTER_STL);
const DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
CFileDialog dlg(TRUE, _T("stl"), NULL, dwFlags, (LPCTSTR)strFilter);
if (dlg.DoModal() != IDOK) {
return;
}
// STLファイル読み込み
CWaitCursor wc;
if (!m_ctTriangles.ReadText((LPCTSTR)dlg.GetPathName())) {
// 読み込みエラー
AfxMessageBox(IDS_ERROR_READ_TEXT);
}
}
正しくファイルを開いて先頭行が読み込まれているか確認してみましょう。
CgsTriangle.cpp を開き bool CgsTriangles::ReadText(const std::wstring& path) の std::getline(ifs, str); 行の後にブレイクポイントを設定します。ブレイクポイントの設定には行数表示してある左側にマウスカーソルを持っていくと●が表示されるのでそこをクリックすると●に色が変わりブレイクポイントが設定されます。メニューの [デバッグ(D)]-[デバッグの開始(S)] を実行して「house.stl」を読み込んでみるとブレイクポイントの設定された●の位置まで実行されると停止するので、下図の様に変数 stl に先頭行が読み込まれていることが確認できるでしょう。
ブレイクポイント●をクリックすればブレイクポイントが解除されます。