Origin Cに引数を渡す
Passing-Arguments-to-OC
概要
LabTalkとOriginCの間で作業する場合、コードで変数を渡す必要がある場合があります。LabTalkでは、数値変数(int、doubleなど)、文字列変数、および列レベルの範囲変数を直接渡すことができます。他のLabTalkオブジェクト(ワークシート範囲、グラフページ範囲など) は文字列で渡され、Origin C関数内でこれらの文字列を操作する必要があります。次の表は、LabTalkからOrigin Cに値を渡すときに関数の引数を処理する方法をまとめたものです。
LabTalkのデータ型 |
Origin C の引数 |
参照渡しをサポート |
double |
double |
可 |
int |
int |
可 |
string |
string |
可 |
column level range |
DataRange |
不可 |
range |
string |
不可 |
string registers |
string |
不可 |
loose dataset |
vector |
不可 |
string array |
vector<string> |
不可 |
tree |
Tree |
可 |
以下のサンプルでさまざまなケースへ対処法を紹介しています。
サンプル
int型を値で渡す
このサンプルでは、Xインデックス番号に基づいて曲線に作用するトレース補間を行い、データの連続的な面を保持して補間します。サンプルでは、Origin CとLabTalkの組み合わせて使用します。曲線の次数を表す整数n が、LabTalkでOrigin Cに渡されます。
Origin C コード:
#include <origin.h>
#define aa 0.5
void main_Data(int n)
{
vector<double> x={0}, y={0};
hilbert_2D(n, x, y);
Worksheet wks=Project.ActiveLayer();
if (wks){
Dataset c1(wks,0);
Dataset c2(wks,1);
c1=x;
c2=y;
}
}
void hilbert_2D(int n, vector<double> &x, vector<double> &y) //ヒルベルト曲線を作成
{
vector x0 = {0}, y0 = {0};
while(n-->0){
x0=x; y0=y;
x.RemoveAll();
y.RemoveAll();
x.Append(aa*(-aa+y0));
x.Append(aa*(-aa+x0));
x.Append(aa*(aa+x0));
x.Append(aa*(aa-y0));
y.Append(aa*(-aa+x0));
y.Append(aa*(aa+y0));
y.Append(aa*(aa+y0));
y.Append(aa*(-aa-x0));
}
}
LabTalkスクリプト:
newbook name:="Trace_Interp";
main_Data(4); // 4次のヒルベルト曲線
interp1trace -r 2 iy:=[Trace_Interp]1!(A,B) method:=spline; //スプライン法でトレース補間.
plotxy iy:=((1,2),(3,4)) plot:=200;
set %C -w 1500; // 線の太さを設定
double型を値で渡す
double、int、string変数をOrigin C関数に直接渡すことができます。
Origin C コード:
#include <origin.h>
double GetLarger(double a, double b)
{
return a>b?a:b;
}
LabTalkスクリプト:
double a = 3.5, b = 8.9;
double c = GetLarger(a, b);
ty "The larger value is $(c)";
整数を参照で渡す
double、int、string型などは参照で渡すこともできます。
Origin C コード:
LabTalkスクリプト:
int a = 10, b = 20;
ty "First, a = $(a), and b = $(b)";
MySwap(a, b);
ty "Then, a = $(a), and b = $(b)";
文字列を参照で渡す
文字列変数はOrigin C関数に直接渡すことができ、参照でも渡せます。
Origin C コード:
#include <origin.h>
int CheckFile(string& strFile, string& strExt)
{
int nRet = strFile.IsFile();
if(nRet != 0)
{
separate_file_name_ext(strFile, NULL, &strExt);
strFile = GetFileName(strFile, TRUE);
}
return nRet;
}
LabTalkスクリプト:
string strFile$ = %Y;
strFile$ =strFile$+"origin.ini";
string strExt;
CheckFile(strFile$, strExt$);
ty "strFile=%(strFile$), strExt=%(strExt$)"
文字列配列を渡す
vector を使用して、Origin C内で文字列配列またはルースデータセットのコピーを作成できます。
Origin C コード:
#include <origin.h>
void TyMyLove(vector<string> strA)
{
int nSize = strA.GetSize();
for(int i=0; i<nSize; i++)
{
printf("I Love %s!\n", strA[i]);
}
}
LabTalkスクリプト:
stringarray aa;
aa.Add("Boston");
aa.Add("New York");
aa.Add("Los Angeles");
TyMyLove(aa);
列範囲を渡す
列範囲変数は直接渡せます。
以下のサンプルで、列変数をOrigin Cに渡す方法を示しています。
必要なOriginのバージョン: 9.0 SR1以降
Origin C コード:
#include <origin.h>
double MyMean(DataRange dr)
{
double dMean;
int nN;
vector vec;
dr.GetData(&vec, 0);
int nRet = ocmath_basic_summary_stats(vec.GetSize(), vec, &nN, &dMean);
if(0 == nRet)
return dMean;
return NANUM;
}
LabTalkスクリプト:
newbook;
col(1) = data(0, 100);
range rr = [%H]1!1;
double Rmean=MyMean(rr);
ty "The Mean of %(rr) is $(Rmean)";
Note:
- rangeは、1つの列だけでなく、列の範囲も参照できます。たとえば、range [book1]sheet1!1[2]:2[5] は、Origin C関数内で直接解釈できます。
- バージョン9のSR1より前のバージョンでは、rangeを使用する場合、範囲名を文字列として Origin C関数に渡す必要がありました。範囲を文字列として渡す方法については、以下のセクションを参照してください。
|
ワークシート範囲を渡す
ワークシート範囲を渡す場合、%()表記を使用してワークシート範囲名を渡すか、文字列変数を文字列としてOrigin C関数に渡すことができます。Origin C 関数内では、okxf_resolve_string_get_origin_object()関数 (xfutils.hを含める) によって文字列を適切なオブジェクトにするか、文字列から適切なオブジェクトを作成することもできます。
LabTalkスクリプトで範囲名を引用するか、文字列変数を直接使用して、文字列を明示的に渡す必要があります。
Origin C コード:
#include <Origin.h>
#include <xfutils.h>
int MyCopyWks(string strSource, string strTarget)
{
Worksheet sWks, tWks;
int nRet = okxf_resolve_string_get_origin_object(strSource, &sWks);
nRet *= okxf_resolve_string_get_origin_object(strTarget, &tWks);
if( !nRet )
{
printf("Worksheet name is wrong!\n");
return 0;
}
sWks.CopyTo(tWks, 0, -1, 0, -1, 0);
return 1;
}
LabTalkスクリプト:
range ra = [book1]sheet1!;
range rb = [book2]sheet1!;
int nRet = MyCopyWks("%(ra)", "%(rb)");
作図範囲を渡す
ワークシート範囲の操作と同様に、プロット範囲を文字列としてOrigin Cに渡すこともできます。
LabTalkとOrigin C間でやり取りする場合、開始インデックスが異なることに注意してください。
Origin C コード:
#include <Origin.h>
#include <xfutils.h>
int ChangeDPColor(string strDP, int nColor)
{
DataPlot dp;
int nRet = okxf_resolve_string_get_origin_object(strDP, &dp);
if( !nRet )
{
printf("Not a valid data plot!\n");
return 0;
}
if( nColor < 1 || nColor > 24 )
{
printf("LabTalk color number sould be 1 ~ 24!\n");
}
// Origin Cの色インデックスは0から開始
nColor--;
dp.SetColor(nColor, TRUE);
return 1;
}
LabTalkスクリプト:
newbook;
col(1) = data(1, 10);
col(2) = col(1);
white_noise 2;
plotxy 2 202;
Range dp = [%H]1!1;
string strDP$ = %(dp);
int nC = color(green);
int nRet = ChangeDPColor(strDP$, nC);
ウィンドウ名を渡す
ウィンドウ名をOrigin C関数に直接渡すことができます。適切なオブジェクトコンストラクターがあれば、Origin Cで対応するオブジェクトを作成できます。
Origin C コード:
#include <Origin.h>
int GetPlotsNum(string pName)
{
int nPlots = 0;
GraphPage gp(pName);
if( !gp.IsValid() )
{
printf("Not a valid page!\n");
return 0;
}
foreach( GraphLayer gl in gp.Layers )
{
foreach( DataPlot dp in gl.DataPlots )
nPlots++;
}
return nPlots;
}
LabTalkスクリプト:
newbook;
string fname$ = system.path.program$;
fname$ += "Samples\Curve Fitting\Exponential Decay.dat";
impasc;
worksheet -s 0 0 -1 -1;
worksheet -p 201;
int nPlots = GetPlotsNum("%H");
ty "There are $(nPlots) plots in %H";
ツリーを渡す
ツリーをOrigin Cに直接渡すことができます。
Origin C コード:
#pragma labtalk(4)
int tt(Tree& tr, string strAppsPath)
{
Tree tr1;
if(!tr1.Load(strAppsPath))
return 1;
tr.Replace(tr1, TRUE, TRUE);
return 0;
}
#pragma labtalk(0)
LabTalkスクリプト:
Tree tr1;
string strApps$="%@AOpxList.xml";
if(0==tt(tr1,strApps$))
tr1.=;
LabTalkツリーをXMLで構成する
LabTalkツリーをXMLで構成できます。
XML用のOrigin C コード:
string st(string strAppsPath)
{
string str;
Tree tr;
if(tr.Load(strAppsPath)) {
tr.GetString(str);
return str;
}
}
LabTalkスクリプト:
string strApps$="%@AOpxList.xml";
string strXML$ = st(strApps$)$;
Tree tr1 = strXML$;
tr1.=
これはデータコネクタで使用できます。例えば、CSVファイルをインポート後以下のスクリプトを実行するとインポートダイアログ設定を取得できます。
Tree tr1=wks.dc.optn$;
tr1.=;
また、その逆もサポートされています。
string str$ = wks.dc.optn$;
Tree tr1 = str$;
tr1.=;
文字列で範囲を返す
ほとんどのOrigin CオブジェクトはLabTalkに返せません。したがって、rangeを返したい場合は、GetRangeString() メソッドを使用して範囲文字列をLabTalkに返すことができます。
Origin C コード:
#include <origin.h>
#include <xfutils.h>
// この関数は、strWksNameのデータを使用してレイヤstrGLに3D散布図を挿入
int Insert3DScatter(string strGL, string strWksName)
{
// 名前でグラフレイヤオブジェクトを取得
GraphLayer gl;
if( !okxf_resolve_string_get_origin_object(strGL, &gl) )
{
out_str("Invalid graph layer!");
return 0;
}
// 名前でワークシートを作成
Worksheet wks(strWksName);
DataRange dr;
int nR = 0;
dr.Add("X", wks, 0, 0, -1, 0);
dr.Add("Y", wks, 0, 1, -1, 1);
nR = dr.Add("Z", wks, 0, 2, -1, 2);
// 3D散布図を追加
int nPlot = gl.AddPlot(dr, ID_3D_GRAPH_SCATTER);
if( nPlot == -1 )
{
out_str("Cannot add plot!");
return 0;
}
DataPlot dp = gl.DataPlots(nPlot);
Tree tr;
tr = dp.GetFormat(FPB_ALL, FOB_ALL, TRUE, TRUE);
tr.Root.Symbol.Shape.nVal = 11;
tr.Root.Symbol.Interior.nVal = 8;
tr.Root.Symbol.EdgeColor.nVal = 15;
tr.Root.DropLines.Z.nVal = 0;
if( !dp.ApplyFormat(tr, TRUE, TRUE) )
{
out_str("Apply format failed!");
return 0
}
return 1;
}
// この関数は透明なメッシュ グラフを作成
// グラフレイヤ名strGLNameは参照によって渡され、
// LabTalk でこの変数を再利用可能
int CreateMeshPlot(string strMOName, string& strGLName)
{
// 行列オブジェクトを名前で取得
MatrixObject mo(strMOName);
okxf_resolve_string_get_origin_object(strMOName, &mo);
GraphPage gp;
gp.Create("mesh");
GraphLayer gl = gp.Layers();
// レイヤにメッシュプロットを追加
int nPlot = gl.AddPlot(mo, IDM_PLOT_3D_MESH);
if( nPlot < 0 )
{
out_str("Cannot create 3D mesh!");
return 0;
}
// プロットを微調整
DataPlot dp = gl.DataPlots(nPlot);
Tree tr;
tr = dp.GetFormat(FPB_ALL, FOB_ALL, TRUE, TRUE);
tr.Root.Grids.FrontColor.nVal = 8;
tr.Root.Grids.BackColor.nVal = 8;
tr.Root.Grids.Width.dVal = 0.8;
tr.Root.Grids.Color.dVal = 19;
tr.Root.Grids.Transparency.nVal = 70;
if( !dp.ApplyFormat(tr, TRUE, TRUE) )
{
out_str("Apply format failed!");
return 0
}
// グラフレイヤの範囲文字列を返す
gl.GetRangeString(strGLName);
gl.Rescale();
return 1;
}
LabTalkスクリプト:
newbook;
string fname$ = system.path.program$;
fname$ += "Samples\Matrix Conversion and Gridding\XYZ Random Gaussian.dat";
impasc;
range rw = [%H]1!3;
rw.type = 6;
xyz_renka iz:=rw rows:=20 cols:=20;
range rm = [%H]1!1;
// 範囲を文字列として渡し、文字列変数を参照で渡す
string strGLName$;
CreateMeshPlot("%(rm)", strGLName$);
// 2秒待つ
sec -p 3;
string strWksName$ = rw.GetLayer()$;
// レイヤ名、ワークシート名を文字列として渡す
Insert3DScatter(strGLName$, strWksName$);
|