Origin Cに引数を渡す

概要

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に渡されます。

Tract int.png

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:
  1. rangeは、1つの列だけでなく、列の範囲も参照できます。たとえば、range [book1]sheet1!1[2]:2[5] は、Origin C関数内で直接解釈できます。
  2. バージョン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$);