本項では前項で読み込んだ座標値を含む文字列から座標値を値として取り出して保持することを目指します。
CgsVector/CgsPointに値を保持させるには、文字列を座標値に変換してから既にあるコンストラクタでインスタンス化しても良いですが、文字列を受け取って座標値に変換してくれるようなコンストラクタがあればそのような処理は必要なくなります。新たにコンストラクタを追加して、実際に三角形データを保持してみましょう。
CgsVector に文字列を渡すコンストラクタを追加して、コンストラクタ内で文字列から座標値に変換する処理を追加します。
1. wstring を引数とするのでヘッダーファイルを追加します。
【CgsVector.h】
#pragma once
#include <string>
class CgsVector
/* 長くなるので一部省略、ここより下は変更なし */
2. ベクトル値の文字列を引数として渡してメンバー変数に保持するコンストラクタを宣言します。
【CgsVector.h】
class CgsVector
{
public:
CgsVector(const double& x = 0.0, const double& y = 0.0, const double& z = 0.0)
: m_dX(x), m_dY(y), m_dZ(z)
{
}
CgsVector(const std::wstring& str);
/* 長くなるので一部省略、ここより下は変更なし */
};
3. ベクトル値の文字列を引数として渡してメンバー変数に保持するコンストラクタを定義します。
【CgsVector.cpp】
#include "pch.h"
#include "CgsVector.h"
CgsVector::CgsVector(const std::wstring& str)
{
wchar_t* p = nullptr;
m_dX = wcstod(str.c_str(), &p); // X値変換
m_dY = wcstod(p, &p); // Y値変換
m_dZ = wcstod(p, &p); // Z値変換
}
CgsPoint でも先ほどと同様に文字列を渡すコンストラクタを追加して、コンストラクタ内で文字列から座標値に変換する処理を追加します。
1. wstring を引数とするのでヘッダーファイルを追加します。
【CgsPoint.h】
#pragma once
#include <string>
class CgsPoint
/* 長くなるので一部省略、ここより下は変更なし */
2. 座標値の文字列を引数として渡してメンバー変数に保持するコンストラクタを宣言します。
【CgsPoint.h】
class CgsPoint
{
public:
CgsPoint(const double& x = 0.0, const double& y = 0.0, const double& z = 0.0)
: m_dX(x), m_dY(y), m_dZ(z)
{
}
CgsPoint(const std::wstring& str);
/* 長くなるので一部省略、ここより下は変更なし */
};
3. 座標値の文字列を引数として渡してメンバー変数に保持するコンストラクタを定義します。
【CgsPoint.cpp】
#include "pch.h"
#include "CgsPoint.h"
CgsPoint::CgsPoint(const std::wstring& str)
{
wchar_t* p = nullptr;
m_dX = wcstod(str.c_str(), &p); // X値変換
m_dY = wcstod(p, &p); // Y値変換
m_dZ = wcstod(p, &p); // Z値変換
}
1. CgsVector のコンストラクタに文字列を渡して double 型の X, Y, Z 値に変換します。str には先頭に「facet normal」とあるのでこれを除いた形で渡します。
【CgsTriangle.cpp】
bool CgsTriangle::ReadText(std::wifstream& ifs)
{
/* 長くなるので一部省略、ここより上は変更なし */
if (count == 0 && str.find(L"facet normal") == 0) {
// 法線ベクトル読み込み
m_cvNormal = { str.substr(12) };
++count;
continue;
}
/* 長くなるので一部省略、ここより下は変更なし */
}
2. CgsPoint のコンストラクタに文字列を渡して double 型の X, Y, Z 値に変換します。str には先頭に「vertex」とあるのでこれを除いた形で渡します。
【CgsTriangle.cpp】
bool CgsTriangle::ReadText(std::wifstream& ifs)
{
/* 長くなるので一部省略、ここより上は変更なし */
else if (1 < count && count < 5 && str.find(L"vertex") == 0) {
// 頂点読み込み
m_cpPoints[count - 2] = { str.substr(6) };
++count;
continue;
}
/* 長くなるので一部省略、ここより下は変更なし */
}
正しく法線ベクトルと座標が読込めているか確認してみましょう。
「法線ベクトルと座標読み込みの呼び出し」で追加した m_cvNormal = { str.substr(12) }; と m_cpPoints[count - 2] = { str.substr(6) }; の 後にある++count; の行にブレイクポイントを設定してメニューの [デバッグ(D)]-[デバッグの開始(S)] を実行して「house.stl」を読み込んでみましょう。下図の様に法線ベクトルが読み込まれ、F5キーを押下する毎に座標が読み込まれていくでしょう。
ブレイクポイントを一旦全て削除した後、bool CgsTriangles::ReadText(const std::wstring& path)の最後の return !empty(); にブレイクポイントを設定し、F5キーを押下すると「house.stl」の全ての三角形が読み込まれ、1479個の三角形が確認できます。