AFsoft WebSite(エーエフソフト・ウェブサイト)
 

オペレーティング・システムについて

プログラミングについて
ホームページについて
キャドについて
電子カタログについて
書籍・雑誌
イベント
リンク集
CAD作ろ! アンドゥ・リドゥ(1)
ここでは、アンドゥ(UNDO;元に戻す)・リドゥ(REDO;やり直す)について考えます。アンドゥ・リドゥを実現する基本的な考え方としてよくあるのは、以前の情報をメモリやHDDに保存しておき、それを利用する、というものです。この保存場所の事を一般的に「バッファ」と呼ぶ事が多いようです。
何かした!
直前の情報を
バッファへコピー
処理
処理を取り消したい場合、現在の状態をクリアし、
コピーした内容を呼び出すと、元に戻す事が出来る
 
この場合1回分しか戻せないので、複数回分戻したい場合には、複数個のバッファを用意し、その個数分、バッファへコピーしなければならない事と、何か処理をするたびに、バッファへのコピーをしなければならない事が、データ量が多い場合、デメリットとなります。
文字の場合には、Delphiの Edit コンポートネントに「取り消しバッファ」という機能が搭載されており、自動的にこのバッファに入るので、アンドゥをする場合には「Edit1.Undo;」とすれば良いようになります。単一の文字データは容量も小さいので速度的にも問題は無いでしょう。
画像ソフトの場合には、例えば、320×240ドット・256色のBMPデータだと 76KB、フルカラーでも 225KBという程度ですが、ドット数・色数が増えれば増える程、データ容量も大きくなっていきます。
CADソフトの場合には、図面の描き始めは線数も少ないので、データ容量は小さいですから、データ容量や速度の問題は軽微でしょう。しかし、線数が多くなればなるほど、問題となってきます。
リドゥにも対応する場合には、アンドゥを行う直前のデータをリドゥ用バッファにコピーするか、又は、1要素ずつスワップ(値の入れ換え)を行う必要があります。
ここで、アンドゥ・リドゥで動的配列のデータをコピーするのに Copy関数を利用しています。通常の変数の場合には、
var
 a , b : Integer;

 b := a ;
のようにすると変数内容のコピーになりますが、動的配列も同様に
var
 a , b : array of Integer;

 b := a ;
のように出来るのではないか?と思ってしまうかもしれませんが、これはうまく行きません。この場合の「a」や「b」は、ポインタ、つまり、データ内容のある場所を示しているだけで、データ全てを抱え込んでいる訳ではないからです。
例えば、住所録で、ある人の住所を変更したとしても、実際の引越作業をしていなければ、その住所を訪ねてもその人は居ない、って事になります。
 
 
上記のサンプルプログラムは、アンドゥ・リドゥは1回しか出来ませんでした。これを複数回にしたいのであれば、単純に考えれば、アンドゥ回数分のバッファを用意すれば良い、という事になりそうです。となれば、単純に、
UndoBuf : array of TDataEntities;
     ↓
UndoBuf1,UndoBuf2,UndoBuf3 : array of TDataEntities;
等のようにやってしまう場合はほとんど無いと思いますが、こういう場合は、動的配列の2次元配列を利用すると良いでしょう。
UndoBuf : array of array of TDataEntities;
と宣言しておき、例えば、
SetLength(UndoBuf,20,10);
SetLength(〜,行数,列数);
とすれば、
  UndoBuf[0][0] 〜 UndoBuf[19][0]
        ・・・・
  UndoBuf[0][9] 〜 UndoBuf[19][9]
が使えるようになります。
  UndoBuf[0,0] 〜 UndoBuf[19,0]
        ・・・・
  UndoBuf[0,9] 〜 UndoBuf[19,9]
と書く事も出来ます。
 
しかしこの場合、各行で使える数は変わってきますので、こういう領域確保の仕方をする事は出来ません。個別に行う必要があります。
SetLength(UndoBuf,20);
SetLength(〜,行数);
と外側の領域確保をし(この場合はアンドゥは20回可能)、更に、
SetLength(UndoBuf[0],10);
SetLength(〜,第0行,列数);
と内側の領域確保を行うようにします。この10は要素数を示します。
 
アンドゥバッファを確保し、作図・編集を行う直前に、全要素をアンドゥバッファにコピーする作業を行うとした場合、複数あるうちの何個目のアンドゥバッファに入れるのか?という管理と、どこまで戻せるのか?という管理を行う必要があります。
例えば、アンドゥを100回まで可能にする場合、No.0からNo.99まで入れて行く訳ですが、これを越えるNo.100に入れる事は出来ません。その場合、No.1〜No.99を、No.0〜No.98に詰め直す作業をするのか?となると、時間が掛かってしまうだろうと容易に想定出来ますので、この場合、No.100ではなく、No.0に入れる事にします。この場合、アンドゥをしたら、No.0→No.99→No.98→・…→No.2→No.1 のように処理を行います。最後は必ずNo.0である、というような処理では無い訳です。
また、アンドゥは、作図・編集を新たに行った場合、以前のアンドゥ内容は破棄される、というのが通常のパターンです。しかし、実際にアンドゥ情報をクリアさせる必要は無いと判断してそのまま続行して使う場合もあれば、勿論、メモリ消費量が多少でも勿体ないからという事で領域解放を行い変数を0にリセットする場合もあります。しかしそれが原因で時間が掛かり速度も落ちるのであれば…という判断も必要になるでしょう。
 
CAD装置(1)
CAD装置(2)
メディア
AutoCADの
DIESELマクロ
CSV
DXF
PCES
IGES
STEP
数学とCAD
CAD作ろ!
 ▲PREV
 ▼NEXT
 
お問い合わせ 
本サイトはリンクフリーです
リンクバナー
(C)Copyright 1999-2015 By AFsoft All Rights Reserved.