うしブログ

うしブログ

趣味で運営する、GeoGebraの専門ブログ。

(作業メモ)StartPoint要検証(2行の場合;テキスト変更時未定義問題)

(要修復)ToggleButton・RollPolygonWithoutSlipping・貯金時計・直感力トレーニング

従属オブジェクトの定義をネストする

課題

たとえば、以下のオブジェクトを、上から順に作成する。

C = (1,1)

r = 2

s = r+1

d = Circle[C,r]

e = Circle[C,s]

output = (Area[e] - Area[d]) / (s^2-r^2)

ここで、JavaScript関数

nest( 'output', ['C','r'] );

を実行することで、outputを、Cとrのみを用いて定義した文字列

 '( Area[Circle[C,r+1]] - Area[Circle[C,r]] ) / ( (r+1)^2-r^2 )'

を取得したい(当該文字列を関数の戻り値としてもよいが、さしあたり、ブラウザのコンソールに出力できれば十分である)。

このように、ある従属オブジェクトの定義を、指定したオブジェクトのみで表した場合の文字列を得られるような、関数nestを作成せよ。

※これができると、オリジナルツール作成が、とても捗る。 

関数作成例

//nest('f', ['a', 'b']):a,b以外の従属オブジェクトを用いないように、fの定義をネストして、コンソールに出力する。(まず使わないと思うが)オブジェクト名にOBJECT+数値+USIDESUを使わないように注意。
function nest(objName, objectToProtectArray){

  //フェイルセーフ
  if(!ggbApplet.exists(objName)){return objName+' is undefined.';}  //objNameが存在しないとき処理終了
  if(ggbApplet.getCommandString(objName, false)==''){return 'it is a freeObject.';}  //ターゲットが自由オブジェクトなら処理終了
  if(!objectToProtectArray){var objectToProtectArray = [];}  //objectToProtectArrayがundefinedのとき[]を代入

  //名前変更前のオブジェクト名リストを取得
  var originalNameArray = ggbApplet.getAllObjectNames();
  //ターゲットのindexを取得
  var indexOfTarget = originalNameArray.indexOf(objName);
//  console.log('indexOfTarget→'); 
//  console.log(indexOfTarget); 

  //保護オブジェクト配列の(originalNameArrayにおける)indexを取得
  var indexArrayOfObjectToProtect = objectToProtectArray.map(function(value){
    return originalNameArray.indexOf(value);
  });
//  console.log('indexArrayOfObjectToProtect→'); 
//  console.log(indexArrayOfObjectToProtect); 

  //名前変更
  for(var k=0; k<originalNameArray.length; k++){
    ggbApplet.renameObject(originalNameArray[k], 'OBJECT'+k+'USIDESU');
  }

  //名前変更後のオブジェクト名リストを取得
  var changedNameArray = ggbApplet.getAllObjectNames();

  //名前変更後のターゲット名を取得
  var changedNameOfTarget = ggbApplet.getObjectName(indexOfTarget);
  //ターゲットの定義を取得
  var definitionOfTarget = ggbApplet.getCommandString(changedNameOfTarget, false);
//  console.log('definitionOfTarget→'); 
//  console.log(definitionOfTarget); 
  //名前変更後の保護オブジェクトの名前リストを取得
  var changedNameArrayOfObjectToProtect = indexArrayOfObjectToProtect.map(function(value){
    return ggbApplet.getObjectName(value);
  });
//  console.log('changedNameArrayOfObjectToProtect→'); 
//  console.log(changedNameArrayOfObjectToProtect); 

  //ネスト処理ループ
  do{
    //親オブジェクトの名前リストを取得
    var nameOfParentObjects = definitionOfTarget.match( /OBJECT\d+USIDESU/g );
    if(!nameOfParentObjects){nameOfParentObjects = [''];}
//    console.log('nameOfParentObjects→'); 
//    console.log(nameOfParentObjects); 
    //親オブジェクトの定義を取得(ただし保護オブジェクトは''扱い)
    var definitionOfParentObjects = nameOfParentObjects.map(function(value){
      if(changedNameArrayOfObjectToProtect.indexOf(value)!=-1){return '';}
      else{return ggbApplet.getCommandString(value, false);}
    });  //自由オブジェクトおよび保護オブジェクトは''をとる
//    console.log('definitionOfParentObjects→'); 
//    console.log(definitionOfParentObjects); 
    //ネスト
    var nestedDefinitionOfTarget = definitionOfTarget;
    for(var k=0; k<nameOfParentObjects.length; k++){
      if(definitionOfParentObjects[k]!=''){
        var re = new RegExp(nameOfParentObjects[k], 'g');
        nestedDefinitionOfTarget = nestedDefinitionOfTarget.replace(re, '('+definitionOfParentObjects[k]+')');
      }
    }
//    console.log('nestedDefinitionOfTarget→');
//    console.log(nestedDefinitionOfTarget);
    definitionOfTarget = nestedDefinitionOfTarget;
  } while (definitionOfParentObjects.join('')!='');

  //ネスト定義文字列の名前を戻す
  for(var k=0; k<originalNameArray.length; k++){
    var usidesuReg = new RegExp(changedNameArray[k], 'g');
    nestedDefinitionOfTarget = nestedDefinitionOfTarget.replace(usidesuReg, originalNameArray[k]);
  }

  //console.log('nestedDefinitionOfTarget→');
  console.log(nestedDefinitionOfTarget);

  //名前を戻す
  for(var k=0; k<originalNameArray.length; k++){
    ggbApplet.renameObject('OBJECT'+k+'USIDESU', originalNameArray[k]);
  }

}