サポート > PC-MAPPING ヒント集 > スクリプト > スクリプトによるスナップしたノード・ポイントの同時移動
スクリプトによるスナップしたノード・ポイントの同時移動
PC-Mappingのベクター構造上、ノードはアークの端点に自動発生し、ノードを移動するとアークも追従します。
例えば、下水道データ「マンホール」「下水管」の場合、PC-Mappingのベクター構造上、「マンホール」ポイントと「下水管」アークに分けるよりも、「下水管」アークのノードを「マンホール」として利用した方が、扱い易くなります。
納品のためエクスポートするときにポイントでなければいけないのであれば、[編集]-[編集]-[編集作図]-[アーク・ノードからポイント生成]を実行し、ノードからポイントを生成してからエクスポートしてはいかがでしょうか。
他にも、1アーク1ポリゴン構造の場合、隣接ポリゴンで補間点・ノードがダブる箇所は、[作図]-[アーク・ノード]-[補間点操作]-[補間点操作(ダブリアーク対応)]で同時移動する事ができます。
それでも、ノード(アーク)とポイントを別レイヤーに分けて管理する必要があり、ノードとポイントの座標点を一致させるため、ポイントを移動したときは、ノードも一緒に移動したいのであれば、スクリプトを作成します。
ここでは、PcmAutoPcmLayerClass:PntMove()メソッド、ArcModifyPos()メソッドの使用例として、スナップしたポイント付近にある別レイヤーのノードも同時に移動するスクリプトをご紹介します。
なお、ここでは行いませんが、補間点も対象にして同時に移動できるよう機能を追加する事も可能です。
■ サンプル
サンプル[script48.zip(約31KB)]をダウンロードする
sample.pcm:サンプルプロジェクト

■ 準備
  1. ダウンロードしたファイルを解凍します。
    ここでは、「C:\sample\script48」とします。

  2. PC-Mappingを起動します。

  3. 「C:\sample\script48\sample.pcm」を開きます。

  4. [プロジェクト]-[プロジェクトエキスパート]から「スクリプト」パネルを開きます。

  5. 「スクリプト」パネルは、ウィンドウ右下の角をドラッグ&ドロップする事で、広げる事ができます。
    「スクリプト」パネルが見にくければ、【編集>>】ボタンをクリックし、スクリプトエディターで開く事ができます。

■ 解説

要点1
function pcmvecmove()
本スクリプトは、プロジェクトに埋め込む事で、「pcmvecmove」コマンドとして実行できるようにしています。

要点2
var aDisp2 = prj.EnvLong(6);
var aSize2 = prj.EnvDouble(3);
var aType2 = prj.EnvLong(5);
var temp = pcmSetAperture(prj, 1, aSize, aType);

[プロジェクトエキスパート]-[環境-2]パネルにある「ベクター要素検索処理」は、座標点からベクターを検索するPcmAutoPcmLayerClass:FindByPosEx2()メソッドのしきい値としても有効です。
PcmAutoProjectClass:EnvLongプロパティ、EnvDoubleプロパティで現在の設定を取得しています。
202行目にあるpcmSetAperture()関数を実行しています。
「アパーチュアを表示する」On、パラメーターで取得した「アパーチュアサイズ」「アパーチュア形状」へ変更します。
125行目で、処理終了時に元のアパーチュアの設定に戻しています。

要点3
while(true){
var temp = sb.SetText(0, "ベクター同時移動... 左(移動元) 右(キャンセル)", 0);
var temp = doc.DoTrack(0, ap);

while(true)文で無限ループしながら、PcmAutoPcmDocClass:DoTrack()メソッドを実行しています。
マウス入力待ちになりますので、マウス左ボタンをクリックすると、その位置の座標点をap(座標点配列オブジェクト)に保存します。
マウス右ボタンをクリックすると、その位置の座標点はap(座標点配列オブジェクト)に保存されません。
無限ループの扱いには注意して下さい。
無限ループを抜ける処理がなければ、スクリプトは終了しません。
WindowsタスクマネージャーからPC-Mappingを強制終了して下さい。

要点4
for(var i = 0; i < prj.GetNumofLayer(); i++){
var lyr = prj.GetLayer(i, true);
if(lyr.IsCurrent() || lyr.Status == 1){
for(var ii = 0; ii < types.length; ii++){
var temp = lyr.FindByPosEx2(types[ii], ap.GetPos(0, 0, coord), ap.GetPos(0, 1, coord), coord, 8+268435456, al);
for(var iii = 0; iii < al.GetNum(); iii++){
var temp = as.Add(lyr.GetID() + "," + types[ii] + "," + al.Data(iii));
}
}
}
}

PcmAutoPcmLayerClass:IsCurrent()メソッド、lyr.Statusプロパティで前景レイヤーか、表示されているレイヤーを対象とします。
PcmAutoPcmLayerClass:FindByPosEx2()メソッドでap(座標点配列オブジェクト)の座標点からノード・ポイントを検索します。
見つかれば、as(文字配列オブジェクト)へ文字列「レイヤー内部ID,ベクター要素番号,ベクター内部ID」(カンマ区切り)を追加します。

要点5
var temp = sb.SetText(0, "ベクター同時移動... 左(移動先) 右(キャンセル)", 0);
var temp = doc.DoTrack(0, ap);

PcmAutoPcmDocClass:DoTrack()メソッドを実行しています。
マウス入力待ちになりますので、マウス左ボタンをクリックすると、その位置の座標点をap(座標点配列オブジェクト)に保存します。
マウス右ボタンをクリックすると、その位置の座標点はap(座標点配列オブジェクト)に保存されません。

要点6
var temp = prj.UndoStart();
PcmAutoPcmProjectClass:UndoStart()メソッドを実行すると、次にUndoStart()メソッドが実行されるか、スクリプトが終了するまでの処理を1つのアンドゥとして記憶します。
ここでは、ノードとポイントの同時移動処理を記憶しますので、アンドゥを実行すると、ノードとポイントを同時にアンドゥできます。

要点7
for(var ii = 0; ii < lyr.NodeGetNumOfArc(datas[2]); ii++){
var id = lyr.NodeGetArcID(datas[2], ii);
if(id > 0){//始点
var temp = lyr.ArcGetPos(id, ap2);
var temp = ap2.SetPos(0, ap.GetPos(0, 0, coord), ap.GetPos(0, 1, coord), 0.00, coord);
var temp = lyr.ArcModifyPos(id, ap2);
}else if(id < 0){//終点
id = id * -1;
var temp = lyr.ArcGetPos(id, ap2);
var temp = ap2.SetPos(ap2.GetNum()-1, ap.GetPos(0, 0, coord), ap.GetPos(0, 1, coord), 0.00, coord);
var temp = lyr.ArcModifyPos(id, ap2);
}
}

ノードを移動するには、そのノードに接続するアークを取得し、アークを構成する座標点を変更します。
まず、PcmAutoPcmLayerClass:NodeGetNumOfArc()メソッドでノードに接続するアークの数を取得します。
PcmAutoPcmLayerClass:NodeGetArcID()メソッドでノードに接続するアーク内部IDを取得、アーク内部IDが正数であれば始点、負数であれば終点になります。
負数であれば正数に変換してから、PcmAutoPcmLayerClass:ArcGetPos()メソッドでアークを構成する座標点を取得します。
PcmAutoArrayPosClass:SetPos()メソッドで始点であれば1点目、終点であれば最終点を要点5で取得したap(座標点配列オブジェクト)に置き換えます。
PcmAutoPcmLayerClass:NodeGetArcID()メソッドでアークに反映します。

要点8
var temp = lyr.PntMove(datas[2], ap.GetPos(0, 0, coord), ap.GetPos(0, 1, coord), 0.00, coord);
ポイントを移動するには、ポイントの座標点を変更します。
PcmAutoPcmLayerClass:PntMove()メソッドを実行し、要点5で取得したap(座標点配列オブジェクト)に置き換えると、直ぐに反映します。

■ 実行
  1. ベクターウィンドウをアクティブにします。

  2. コマンドラインバーが表示されているか確認します。
    表示されていなければ、[ワークスペース]-[コマンドバー]-[コマンドラインバー]を実行します。

  3. 3. コマンド「pcmvecmove△5△1」と記述し、実行します(アルファベットは半角小文字、△は半角スペース、数字は半角)。
    パラメーター「5」は、[プロジェクトエキスパート]-[環境-2]パネルにある「ベクター要素検索処理」の「アパーチュアサイズ」です。
    パラメーター「1」は、「円形のアパーチュア」です。
    「0」にすれば「矩形のアパーチュア」を指定できます。

  4. すると、マウス入力待ちになり、PC-Mappingウィンドウ左下のステータスバーに「ベクター同時移動... 左(移動元) 右(キャンセル)」と表記されます。

  5. 中央のポイント(赤丸)をマウス左ボタンでクリックします。

  6. すると、マウス入力待ちになり、PC-Mappingウィンドウ左下のステータスバーに「ベクター同時移動... 左(移動先) 右(キャンセル)」と表記されます。

  7. 移動したい位置をマウス左ボタンでクリックします。

  8. すると、「マンホール」レイヤーのポイントだけでなく、「下水道」レイヤーのノードが一緒に移動します。

  9. マウス右ボタンをクリックすると、処理を終了します。

  10. [作図]-[取り消し]-[UNDO(アンドゥ)]を実行すると、元の状態に戻す事ができます。

■ エラーメッセージ
エラーメッセージは、[アウトプットバー]-[メッセージ]パネルに出力しています。
「現状、実行できません」と出力される場合「パラメーターを設定しているか」「プロジェクトを読み込んでいるか」「ベクターウィンドウがアクティブか」、「失敗しました」と出力される場合「対象レイヤーの座標系がペーパー座標系、直角座標系、緯経度座標系のどれかか」「対象レイヤーの座標系が統一されているか」をご確認下さい。