Skip to main content
Participating Frequently
April 4, 2023
Answered

面積計算スクリプトを複数対応に改善したい

  • April 4, 2023
  • 3 replies
  • 2385 views

スクリプトの作成については素人なのですが、

オブジェクトの面積を計算して出力するスクリプトを

(既存スクリプトを組み合わせて改造しながら)作成しました。

 

これは単体のオブジェクトに対してだけ動作するものです。

複数のオブジェクトを選択して実行したとき、

それぞれに計算して合計してくれるような

スクリプトに改善することはできるでしょうか。

 

よろしくお願い致します。

 

//------------変数の初期化等------------
var win_width = 400;  //ウインドウの幅を指定
var win_hight = 110;  //ウインドウの高さを指定
var dlWin;  //ダイアログウインドウを格納する変数
var btnOK;  //OKボタンを格納する変数
var condition_scale;  //スケール変換(文字列)を格納する変数
var scale;  //スケール変換を格納する変数

var area = app.selection[0].area; // 選択中のオブジェクトの面積(単位がpt)を取得

if (isNaN(area)) {
alert ("グループ・複合パス・テキスト等の面積計算はできません。");
}

else {

dlWin = new Window("dialog","スケールの入力",[0,0,win_width,win_hight]);   
dlWin.center();  //ウインドウ表示位置をモニターの中心に移動

dlWin.add ("statictext", [10,10,60,40], "Scale 1/");  //ウインドウに固定文字を追加
condition_scale = dlWin.add("edittext",[60,10,win_width-10,40],10);  //個数nの入力テキストボックスを追加、初期値は10に設定
dlWin.add ("statictext", [10,40,win_width,60], "※オブジェクトが複数ある場合、最前面の1つだけを実行します");  //ウインドウに固定文字を追加

btnOK = dlWin.add("button",[10,70,130,100],"OK",{name:"ok"});  //ウインドウにOKボタンを追加

dlWin.show();  //作成したウインドウを表示

scale = parseInt(condition_scale.text, 10);  //ダイアログで入力したスケールを整数に変換
var absolute = Math.abs(area); // 負の数字を引っ張ってくる場合があるので、絶対値を取得して正の数に統一
var convert = Math.ceil(absolute * 0.12445216049); // 小数点を切り上げしてptからメートル法に変換
var result = (convert * 0.000001 * scale * scale +'㎡'); // スケール変換して計算

var x = app.activeDocument.selection[0].position[0];
var y = app.activeDocument.selection[0].position[1]; // 選択中のオブジェクトのXY座標を取得
docObj = activeDocument;
textObj = docObj.textFrames.add(); 
textObj.contents = (result); //テキストフレームにresultを書き込み
textObj.translate(x,y+2.5); //テキストを選択中のオブジェクトのすぐ上に移動
}

 

This topic has been closed for replies.
Correct answer Uske_S

> それぞれに計算して合計してくれるような

> スクリプトに改善することはできるでしょうか。

ajabon grinsmithさんのは複数選択してそれぞれに面積計算,だったので,合算するものはこんな感じ…?

 

//------------変数の初期化等------------
var win_width = 400;  //ウインドウの幅を指定
var win_hight = 110;  //ウインドウの高さを指定
var dlWin;  //ダイアログウインドウを格納する変数
var btnOK;  //OKボタンを格納する変数
var condition_scale;  //スケール変換(文字列)を格納する変数
var scale;  //スケール変換を格納する変数

var dlWin = new Window("dialog", "スケールの入力", [0, 0, win_width, win_hight]);
dlWin.center();  //ウインドウ表示位置をモニターの中心に移動
dlWin.add("statictext", [10, 10, 60, 40], "Scale 1/");  //ウインドウに固定文字を追加
var condition_scale = dlWin.add("edittext", [60, 10, win_width - 10, 40], 10);  //個数nの入力テキストボックスを追加、初期値は10に設定
dlWin.add("statictext", [10, 40, win_width, 60], "※オブジェクトが複数ある場合、最前面の1つだけを実行します");  //ウインドウに固定文字を追加
var btnOK = dlWin.add("button", [10, 70, 130, 100], "OK", { name: "ok" });  //ウインドウにOKボタンを追加
dlWin.show();  //作成したウインドウを表示

var result = 0;

for (var i = 0; i < selection.length; i++) {
    var area = app.selection[i].area; // 選択中のオブジェクトの面積(単位がpt)を取得
    if (isNaN(area)) {
        alert("グループ・複合パス・テキスト等の面積計算はできません。");
        break;
    }
    else {

        var scale = parseInt(condition_scale.text, 10);  //ダイアログで入力したスケールを整数に変換
        var absolute = Math.abs(area); // 負の数字を引っ張ってくる場合があるので、絶対値を取得して正の数に統一
        var convert = Math.ceil(absolute * 0.12445216049); // 小数点を切り上げしてptからメートル法に変換
        result += (convert * 0.000001 * scale * scale); // スケール変換して計算

    }
}
var x = app.activeDocument.selection[0].position[0];
var y = app.activeDocument.selection[0].position[1]; // 選択中のオブジェクトのXY座標を取得
var docObj = activeDocument;
var textObj = docObj.textFrames.add();
textObj.contents = (result + '㎡'); //テキストフレームにresultを書き込み
textObj.translate(x, y + 2.5); //テキストを選択中のオブジェクトのすぐ上に移動

3 replies

Ten A
Community Expert
Community Expert
April 4, 2023

とりあえず基本を…

なぜareaプロパティが負の数になるのかと言うと、パスのpolarityの問題です。

様々な状況変化によって、複合パスは奇遇規則で処理される事が多くなりましたが、この辺の仕組みはまだワインディング規則です。

複合パス内のpathItemのpolarityがpositiveな部分が正の数値を持ち中窓として抜かれる部分が負の値となっている為に複合パス内のパスの面積はそのまま加算すれば良いことになります。

ただし、これには条件があって、全てのパスが交差しない状態でないと正確な数値になりません。交差した部分がある場合、複合パスをパスファインダーで合体し、全てのpathItemのpolarityを positiveに変更しながら加算すると良いでしょう。

Taro_KSAuthor
Participating Frequently
April 4, 2023

ご教授ありがとうございます。

複合パスもスパッと計算してくれたら便利ですが、難しいのですね。

基本のキもおろそかですので、勉強したいと思います。

Uske_S
Community Expert
Uske_SCommunity ExpertCorrect answer
Community Expert
April 4, 2023

> それぞれに計算して合計してくれるような

> スクリプトに改善することはできるでしょうか。

ajabon grinsmithさんのは複数選択してそれぞれに面積計算,だったので,合算するものはこんな感じ…?

 

//------------変数の初期化等------------
var win_width = 400;  //ウインドウの幅を指定
var win_hight = 110;  //ウインドウの高さを指定
var dlWin;  //ダイアログウインドウを格納する変数
var btnOK;  //OKボタンを格納する変数
var condition_scale;  //スケール変換(文字列)を格納する変数
var scale;  //スケール変換を格納する変数

var dlWin = new Window("dialog", "スケールの入力", [0, 0, win_width, win_hight]);
dlWin.center();  //ウインドウ表示位置をモニターの中心に移動
dlWin.add("statictext", [10, 10, 60, 40], "Scale 1/");  //ウインドウに固定文字を追加
var condition_scale = dlWin.add("edittext", [60, 10, win_width - 10, 40], 10);  //個数nの入力テキストボックスを追加、初期値は10に設定
dlWin.add("statictext", [10, 40, win_width, 60], "※オブジェクトが複数ある場合、最前面の1つだけを実行します");  //ウインドウに固定文字を追加
var btnOK = dlWin.add("button", [10, 70, 130, 100], "OK", { name: "ok" });  //ウインドウにOKボタンを追加
dlWin.show();  //作成したウインドウを表示

var result = 0;

for (var i = 0; i < selection.length; i++) {
    var area = app.selection[i].area; // 選択中のオブジェクトの面積(単位がpt)を取得
    if (isNaN(area)) {
        alert("グループ・複合パス・テキスト等の面積計算はできません。");
        break;
    }
    else {

        var scale = parseInt(condition_scale.text, 10);  //ダイアログで入力したスケールを整数に変換
        var absolute = Math.abs(area); // 負の数字を引っ張ってくる場合があるので、絶対値を取得して正の数に統一
        var convert = Math.ceil(absolute * 0.12445216049); // 小数点を切り上げしてptからメートル法に変換
        result += (convert * 0.000001 * scale * scale); // スケール変換して計算

    }
}
var x = app.activeDocument.selection[0].position[0];
var y = app.activeDocument.selection[0].position[1]; // 選択中のオブジェクトのXY座標を取得
var docObj = activeDocument;
var textObj = docObj.textFrames.add();
textObj.contents = (result + '㎡'); //テキストフレームにresultを書き込み
textObj.translate(x, y + 2.5); //テキストを選択中のオブジェクトのすぐ上に移動
Uske_S
Uske_S
Community Expert
Community Expert
April 4, 2023

手を加えたところを少し補足すると,

 

  1. 選択したもの全部に実行するので,全体をfor文に入れました
  2. result変数にareaの計算を足していきたいので,for文の前で定義して,30行目で result += としてresult変数に値を足していきます
  3. それに伴って単位表記 '㎡' は最後の textObj.contents に代入するタイミングで追加しました
  4. 他には,変数定義に var を追加しました

 

伝わったでしょうか?

Uske_S
Taro_KSAuthor
Participating Frequently
April 4, 2023

早速のご回答ありがとうございます。

補足説明もたいへん勉強になります。

かなり想定に近い挙動ですので、

ajabon grinsmith様の案と組み合わせて

改善、運用していこうと思います。

ajabon grinsmith
Community Expert
Community Expert
April 4, 2023

ちゃらっとしか試してませんがいちおう動きました。

areaプロパティを持たないオブジェクトのぶんは無言でスルーする仕様なので注意してください。

//------------変数の初期化等------------
var win_width = 400;  //ウインドウの幅を指定
var win_hight = 110;  //ウインドウの高さを指定
var dlWin;  //ダイアログウインドウを格納する変数
var btnOK;  //OKボタンを格納する変数
var condition_scale;  //スケール変換(文字列)を格納する変数
var scale;  //スケール変換を格納する変数
var area; // 選択中のオブジェクトの面積(単位がpt)を取得
var x, y; //エックスとワイ

dlWin = new Window("dialog","スケールの入力",[0,0,win_width,win_hight]);   
dlWin.center();  //ウインドウ表示位置をモニターの中心に移動

dlWin.add ("statictext", [10,10,60,40], "Scale 1/");  //ウインドウに固定文字を追加
condition_scale = dlWin.add("edittext",[60,10,win_width-10,40],10);  //個数nの入力テキストボックスを追加、初期値は10に設定
dlWin.add ("statictext", [10,40,win_width,60], "※オブジェクトが複数ある場合、最前面の1つだけを実行します");  //ウインドウに固定文字を追加

btnOK = dlWin.add("button",[10,70,130,100],"OK",{name:"ok"});  //ウインドウにOKボタンを追加

dlWin.show();  //作成したウインドウを表示
scale = parseInt(condition_scale.text, 10);  //ダイアログで入力したスケールを整数に変換

var sel = app.selection; //選択オブジェクトの配列
for(var i = 0 ; i < sel.length; i++){
    area = sel[i].area;

    if (isNaN(area)) {
        //alert ("グループ・複合パス・テキスト等の面積計算はできません。");
        continue;
    }
    
    var absolute = Math.abs(area); // 負の数字を引っ張ってくる場合があるので、絶対値を取得して正の数に統一
    var convert = Math.ceil(absolute * 0.12445216049); // 小数点を切り上げしてptからメートル法に変換
    var result = (convert * 0.000001 * scale * scale +'㎡'); // スケール変換して計算
    x = sel[i].position[0];
    y = sel[i].position[1]; // 選択中のオブジェクトのXY座標を取得
    docObj = activeDocument;
    textObj = docObj.textFrames.add(); 
    textObj.contents = (result); //テキストフレームにresultを書き込み
    textObj.translate(x,y+2.5); //テキストを選択中のオブジェクトのすぐ上に移動
}

 ※すみません投稿後に2回なおしました…

Taro_KSAuthor
Participating Frequently
April 4, 2023

早速のご回答ありがとうございます。とても助かりました。

Uske_S様のご回答と組み合わせて使用させて頂きます。