HDS#07 乱数の生成(デモンストレーション向け)

 

こんにちは、開発Gの杉原です。

 

年度が変われば多少のいとまができる。そう思っていた時期が私にもありました。

3月に多くのお客様にDemo3Dをご購入いただいたのですが、それが4~6月にかけてのモデル開発のご依頼に繋がったというわけです。少し考えれば当然の結果な気もしますね。

とはいっても、別に悪いことではなく、いろいろな方にDemo3Dを使っていただけるようになっているという、大変ありがたい話なわけです。

ということで気を緩めず、引き続き頑張って、満足いただけるものを開発できればと思っております。

 

さて【How to Demo3D Scripting】ですが、今月は乱数についてご紹介させていただきます。

まずは今回、第7回では「乱数の生成(デモンストレーション向け)」をお送りします。

実をいうと乱数はあまり使う機会がないのかなと思っています。

過去のモデル開発の中でも、使ったことはあるものの、全体の中ではごく一部の処理でしかないですし、そもそも自分では乱数を使わないケースも多々あります。

 

しかし

・棚の端から順ではなく、順不同に格納していく様子を表したい

・実行のたびに異なるパターンでシミュレーションしたい

などといった状況で乱数は必ず必要になってきます。

 

 

ということで、まずは簡単な乱数作成プログラムを紹介します。

var rnd = random(10); // 0~9の範囲での乱数値を生成します
print(rnd); // 生成された値を出力
int rnd = app.Document.Random.Next(10);
print(rnd.ToString());

JScriptを使用している場合、乱数を出力するための関数randomが用意されているので、これに引数を渡して呼び出すだけで乱数が取得できます。

C#の場合は残念ながらrandom関数が使えないようなのですが、Documentオブジェクトが乱数を扱うメンバーを持っているようなので、それを利用します。

なお、以後の解説ではJScriptにあわせて「random」と表記しますが、C#の場合はこの「app.Document.Random.Next」に読み替えていただければと思います。

 

このrandomの引数には取得できる最大の値+1を指定します。

得られるのは0~引数ー1の範囲の整数ですので、引数に設定する値は「得られる値のパターン数」と覚えていただければと思います。

 

このrandomを使った例を紹介します。

function DefaultOnSelectBin( sender : Demo3D.Visuals.BoxVisual, load : Visual )
{
    var binLocation = new RackShelfBinLocation();
    
    // Pick a random rack
    var racks : List = GetRacks(sender);
    
    var firstRack = random(racks.Count);
    
    for (var r=0; r < racks.Count; ++r) {
        binLocation.Rack = int( (firstRack + r) % racks.Count );
        var rack  : RackVisual = racks[ binLocation.Rack ];
        // Pick a random starting shelf
        var shelves    = GetShelvesForRack(rack);
        var firstShelf = random(shelves.Count);
        
        for (var i=0; i < shelves.Count; ++i) {
            binLocation.Shelf = int( (firstShelf + i) % shelves.Count );
            var shelf  : ShelfVisual = shelves[ binLocation.Shelf ];
            
            // Get next storage location on that shelf
            var nextLocation : BinLocation = shelf.GetNextStorageBinLocation();
            
            if (nextLocation == null) {
                continue;
            }
            binLocation.Bay = nextLocation.Bay;
            binLocation.Bin = nextLocation.Bin;
            
            // Reserve a space at the selected bin
            shelf.AddLocationProperty(load, binLocation);
            return;
        }
    }
}

上記はQuickStartカタログのASRSフォルダにある「SRM」にあるスクリプトの一部です。

この8行目や15行目を見ていただくと「random」が使用されていることがわかるかと思います。

ここでは「どのラック」の「どの段」に格納するかをランダムで決めています。

 

SRMはラックへの入出庫を管理するためのVisualなので、これを使えばランダムに入庫する様が再現できるわけです。

冒頭に「自分では使わない」と言ったのは、標準でこういったものが用意されているからなんですね。

 

さて、このrandomですが、ちょっとした特徴があります。

その説明のため、新規にBoxVisualを作成し、次のようなScriptを実装してみます。

function Box1_OnInitialize( sender : Demo3D.Visuals.BoxVisual )
{
    for(var cnt = 1; cnt <= 10; cnt++)
    {
        print(cnt +"回目:"+random(10));
    }
}
[Auto]
void OnInitialize(Visual sender){
    for(int cnt = 1; cnt <= 10; cnt++)
    {
        print(cnt + "回目:" + app.Document.Random.Next(10));
    }
}

モデルを実行したときに10回乱数を生成して、メッセージログに出力するスクリプトです。

 

まず一度実行してみます。

結果は上記のようになりました。

 

次に、実行を停止したのちにリセットして、もう一度実行してみます。

2回目の結果は上記のようになりました。

 

1回目の結果を間違えてもう一度貼ってしまったように見えるかもしれません。

しかし、これは貼り間違いやコピペなどではなく、実際に得られた結果として、1回目とまったく同じ結果となったのです。

 

つまり、randomで取得できる乱数は、モデルを実行しなおすたびに全く同じ値を返すというわけなのです。

 

この仕様は、デモンストレーションにあたってはとてもありがたいものだと思っています。

実行するたびに同じように動きますので、出来上がったモデルを人に見せるとき、自分が見たのと違った動きになるということはまず無いはずです。

特に動画を作成するときなんかには、モデルの動きに合わせてタイミングとカメラ位置を調整しますので、常に同じ動きであってほしいものです。

 

しかしながら、このような乱数生成を良しとしないこともあるかと思います。

例えばシミュレーションをするときにランダムな要素を使用する場合、実行するたびに同じ結果となってはシミュレーションの意味がないかと思います。

そこで、また違った手法で乱数を取得する必要がでてくるのです。


 

ということで次回の【How to Demo3D Scripting】は「乱数の生成(シミュレーション向け)」をお送りします。

更新は4/12(木)、ご期待ください。