分析またはグラフ作成時に、ワークシートから行列に変換またはその反対の操作をして、データを再構成する必要があるかもしれません。このページはワークシートを行列に変換する時のサンプルと情報を紹介します。なお、反対の操作をする際は行列をワークシートに変換するを参照してください。
Run.LoadOC(Originlab\nag_utils.c, 16);
#include <wks2mat.h> #include <Nag_utils.h>
// XYZ列からXYZデータ範囲を取得 XYZRange rng; rng.Add(wks, 0, "X"); rng.Add(wks, 1, "Y"); rng.Add(wks, 2, "Z"); // データ範囲オブジェクトからベクターにXYZデータを取得 vector vX, vY, vZ; rng.GetData(vZ, vY, vX);
UINT nVar; double xmin, xstep, xmax, ymin, ystep, ymax; int nSize = vX.GetSize(); int nMethod = ocmath_xyz_examine_data(nSize, vX, vY, vZ, 1.0e-8, 1.0e-8, &nVar, &xmin, &xstep, &xmax, &ymin, &ystep, &ymax);
int nRows = 10, nCols = 10; if( 0 == nMethod || 1 == nMethod ) // XY等間隔または疎データ { double dGap = 1.5; if( !is_equal(ystep, 0) ) nRows = abs(ymax - ymin)/ystep + dGap; if( !is_equal(xstep, 0) ) nCols = abs(xmax - xmin)/xstep + dGap; }
// グリッディング結果を配置する行列ウィンドウを準備 MatrixPage mp; mp.Create("origin"); // 行列ウィンドウを作成 MatrixLayer ml = mp.Layers(0); // 第1行列シートを取得 MatrixObject mo(ml, 0); // 第1行列オブジェクトを取得 mo.SetXY(xmin, ymin, xmax, ymax); // XとYの開始/終了値をセット mo.SetSize(nRows, nCols); // 行と列の数をセット
matrix& mat = mo.GetDataObject(); // 行列オブジェクトからデータオブジェクトを取得 int iRet; switch(nMethod) { case 0: // XY等間隔 iRet = ocmath_convert_regular_xyz_to_matrix(nSize, vX, vY, vZ, mat, xmin, xstep, nCols, ymin, ystep, nRows); printf("--- %d: regular conversion ---\n", iRet); break; case 1: // 疎データ iRet = ocmath_convert_sparse_xyz_to_matrix(nSize, vX, vY, vZ, mat, xmin, xstep, nCols, ymin, ystep, nRows); printf("--- %d: sparse conversion ---\n", iRet); break; case 2: // ランダム(Renka Cline) vector vxGrid(nRows*nCols), vyGrid(nRows*nCols); iRet = ocmath_mat_to_regular_xyz(NULL, nRows, nCols, xmin, xmax, ymin, ymax, vxGrid, vyGrid); if( iRet >= 0 ) { iRet = xyz_gridding_nag(vX, vY, vZ, vxGrid, vyGrid, mat); } printf("--- %d: random conversion ---\n", iRet); break; default: // エラー printf("--- Error: Other method type ---\n"); }
ワークシートに含まれるデータは、一連の関数を使って行列に変換することができます。
行列のようなワークシートデータを直接行列に変換するために、ワークシートの最初の列と行にXまたはYの値を入力します。しかし、行列の座標は等間隔でなければならいので、元のワークシートに等間隔なX/Y値が入力されている必要があります。メソッド CopyFromWks を直接使用するか、単に行列にXYZデータ範囲を付けます。
次のサンプルはワークシートから直接変換する方法を示しています。
// 方法 1: CopyFromWksを使用 Worksheet wks = Project.ActiveLayer(); if(!wks) { return; } MatrixPage matPg; matPg.Create("Origin"); MatrixLayer matLy = matPg.Layers(0); Matrix mat(matLy); matrix<double> mat1; if(!mat1.CopyFromWks(wks, 1, -1, 1, -1)) { out_str("Error: CopyFromWks failed!"); return; } mat = mat1; // 方法 2: 行列オブジェクトに付加 Worksheet wks = Project.ActiveLayer(); if(!wks) { return; } int nCols = wks.GetNumCols(); int nRows = wks.GetNumRows(); DataRange dr; dr.Add("X", wks, 0, 1, 0, nCols - 1); // 最初のセルを除いた最初の行 dr.Add("Y", wks, 1, 0, nRows - 1, 0); //最初のセルを除いた最初の列 dr.Add("Z", wks, 1, 1, nRows - 1, nCols - 1); MatrixPage matPg; matPg.Create("Origin"); MatrixLayer matLy = matPg.Layers(0); MatrixObject mo = matLy.MatrixObjects(0); MatrixObject moTmp; moTmp.Attach(dr); matrixbase &matTmp = moTmp.GetDataObject(); matrixbase &mat = mo.GetDataObject(); mat = matTmp; moTmp.Detach();
ワークシートデータがXYZ列形式で構成されているとき、グリッディング法を使ってこのようなデータを行列に変換します。多くのグリッディング法が利用でき、これにより元のデータを補間し、指定した次数での等間隔なXYで、値の配列を生成します。
次のサンプルでは、Renka-Clineの手法によりXYZデータを変換します。
// Renka-Clineグリッディング手法によりワークシートデータを20*20の行列に変換 Worksheet wks = Project.ActiveLayer(); if(!wks) { return; } Dataset dsX(wks, 0); Dataset dsY(wks, 1); Dataset dsZ(wks, 2); int nPoints = dsX.GetSize(); vector vX = dsX; vector vY = dsY; vector vZ = dsZ; ocmath_RenkaCline_Struct comm; ocmath_renka_cline_interpolation(nPoints, vX, vY, vZ, &comm); //グリッディングのXとYをセット double dXMin, dXMax, dYMin, dYMax; vX.GetMinMax(dXMin, dXMax); vY.GetMinMax(dYMin, dYMax); //Kriging アルゴリズムを使用したランダム行列変換 int nRows = 20; int nCols = 20; matrix mZ(nRows, nCols); vector vEvalX(nRows * nCols); vector vEvalY(nRows * nCols); ocmath_mat_to_regular_xyz(NULL, nRows, nCols, dXMin, dXMax, dYMin, dYMax, vEvalX, vEvalY, NULL, true); ocmath_renka_cline_eval(&comm, nRows * nCols, vEvalX, vEvalY, mZ); ocmath_renka_cline_struct_free(&comm); // 行列を作成して結果を格納 MatrixLayer mResultLayer; mResultLayer.Create(); Matrix matResult(mResultLayer); matResult = mZ; MatrixObject mo = mResultLayer.MatrixObjects(0); mo.SetXY(dXMin, dYMin, dXMax, dYMax);//行列を作成して結果を格納