- ベストアンサー
論理演算機能を使った判断文のコンパクト化方法
- 論理演算機能を使用して判断文をコンパクトにする方法について教えてください。
- 四角ポケットの角に逃がしを入れる際に、X・Y方向に逃がしを入れる場合について教えてください。
- 判断文のコンパクト化において、ORの使用方法についてアドバイスをいただけますか?
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
- ベストアンサー
分かりやすさから1234は譲れないところなのでしょう。 それを判定しやすいビット列に変換するマクロを組めば良いと思います。 下記でどうでしょう。 とりあえず要点以外は定数にしたり、はしょったりしてあります。 #33がIJ指令をビット列に変換したものです。(#31#32は計算用一時変数) bit0( 1)…右上X有無 bit1( 2)…左上X有無 bit2( 4)…左下X有無 bit3( 8)…右下X有無 bit4( 16)…右上Y有無 bit5( 32)…左上Y有無 bit6( 64)…左下Y有無 bit7(128)…右下Y有無 参考になれば幸いです。 ---------- O0001 G65P0002I1234.J1234. M30 O0002 #33=0 N10DO1 #31=#4-FIX[#4/10]*10-1 #32=1 WHILE[#31GT0]DO2 #32=#32*2 #31=#31-1 END2 #33=#33+#32 #4=FIX[#4/10] IF[#4LE0]GOTO20 END1 N20DO1 #31=#5-FIX[#5/10]*10-1 #32=1 WHILE[#31GT0]DO2 #32=#32*2 #31=#31-1 END2 #33=#33+#32*16 #5=FIX[#5/10] IF[#5LE0]GOTO100 END1 N100G0X0Y0 Z5. G1Z-5.F100 X50. Y50. IF[[#33AND1]NE1]GOTO110(右上X) G91X10. X-10. G90 N110IF[[#33AND16]NE16]GOTO120(右上X) G91Y10. Y-10. G90 N120X-50. IF[[#33AND2]NE2]GOTO130(左上X) G91X-10. X10. G90 N130IF[[#33AND32]NE32]GOTO140(左上Y) G91Y10. Y-10. G90 N140Y-50. IF[[#33AND4]NE4]GOTO150(左下X) G91X-10. X10. G90 N150IF[[#33AND64]NE64]GOTO160(左下Y) G91Y-10. Y10. G90 N160X50. IF[[#33AND8]NE8]GOTO170(右下X) G91X10. X-10. G90 N170IF[[#33AND128]NE128]GOTO180(右下Y) G91Y-10. Y10. G90 N180Y0 X0 G0Z100. M99 ---------- すみません、早速ですが訂正です。 ---------- N10DO1 #31=#4-FIX[#4/10]*10-1 #32=1 WHILE[#31GT0]DO2 #32=#32*2 #31=#31-1 END2 #33=#33+#32 #4=FIX[#4/10] IF[#4LE0]GOTO20 END1 N20DO1 #31=#5-FIX[#5/10]*10-1 #32=1 WHILE[#31GT0]DO2 #32=#32*2 #31=#31-1 END2 #33=#33+#32*16 #5=FIX[#5/10] IF[#5LE0]GOTO100 END1 ---------- 下記のほうがGOTO不用でスタイリッシュです。 ---------- WHILE[#4GT0]DO1 #31=#4-FIX[#4/10]*10-1 #32=1 WHILE[#31GT0]DO2 #32=#32*2 #31=#31-1 END2 #33=#33+#32 #4=FIX[#4/10] END1 WHILE[#5GT0]DO1 #31=#5-FIX[#5/10]*10-1 #32=1 WHILE[#31GT0]DO2 #32=#32*2 #31=#31-1 END2 #33=#33+#32*16 #5=FIX[#5/10] END1 ---------- MODを使えば少し分かりやすく書けます。 ---------- WHILE[#4GT0]DO1 #31=[#4MOD10]-1 #32=1 WHILE[#31GT0]DO2 #32=#32*2 #31=#31-1 END2 #33=#33+#32 #4=FIX[#4/10] END1 WHILE[#5GT0]DO1 #31=[#5MOD*10]-1 #32=1 WHILE[#31GT0]DO2 #32=#32*2 #31=#31-1 END2 #33=#33+#32*16 #5=FIX[#5/10] END1 ---------- ですが、16i等ではMODは使えないと思います。 すみません、また訂正です。 ---------- WHILE[#4GT0]DO1 #31=[#4MOD10]-1 #32=1 WHILE[#31GT0]DO2 #32=#32*2 #31=#31-1 END2 #33=#33+#32 #4=FIX[#4/10] END1 WHILE[#5GT0]DO1 #31=[#5MOD*10]-1(<-) #32=1 WHILE[#31GT0]DO2 #32=#32*2 #31=#31-1 END2 #33=#33+#32*16 #5=FIX[#5/10] END1 ---------- WHILE[#4GT0]DO1 #31=[#4MOD10]-1 #32=1 WHILE[#31GT0]DO2 #32=#32*2 #31=#31-1 END2 #33=#33+#32 #4=FIX[#4/10] END1 WHILE[#5GT0]DO1 #31=[#5MOD10]-1(<-) #32=1 WHILE[#31GT0]DO2 #32=#32*2 #31=#31-1 END2 #33=#33+#32*16 #5=FIX[#5/10] END1 ---------- これは、任意のビット位置の0/1を判定する定番の書き方で、 私も他人に教えてもらいました。 >仮にG65P0002I1.J1.だとすると#33=17になると思うのですが、 そのとおり、#33=(10進数)17=(2進数)00010001です。 >IF[[#33AND1]NE1]GOTO110(右上X) (10進数)17=(2進数)00010001 (10進数) 1=(2進数)00000001 -------------------------- (AND) (2進数)00000001=(10進数)1←これを(10進数)1と比較(NE)。 >N110IF[[#33AND16]NE16]GOTO120(右上Y)←すみませんYでした (10進数)17=(2進数)00010001 (10進数)16=(2進数)00010000 -------------------------- (AND) (2進数)00010000=(10進数)16←これを(10進数)16と比較(NE)。 128/64/32/16/8/4/2/1とすることで、 全てのビットを個別に判定できるわけです。
その他の回答 (4)
回答(4)さんの追記に反応して MODが使える世代(31i等)なら、べき乗関数POWも使えるでしょうから 2のべき乗を計算をしている2重目のループが不要に出来ますね。 出来るだけ簡素に書くと WHILE[#4GT0]DO1 #33=POW[2,[#4MOD10]-1]OR#33 #4=FIX[#4/10] END1 WHILE[#5GT0]DO1 #33=POW[2,[#5MOD10]+3]OR#33 #5=FIX[#5/10] END1 ただしこれじゃあまりにも不正値に対して弱いので 気休め程度のエラー処理を追加。 WHILE[#4GT0]DO1 #31=[#4MOD10]-1 IF[#31GT3]THEN#3000=1(I INCORRECT) IF[#31GE0]THEN#33=POW[2,#31]OR#33 #4=FIX[#4/10] END1 WHILE[#5GT0]DO1 #31=[#5MOD10]-1 IF[#31GT3]THEN#3000=1(J INCORRECT) IF[#31GE0]THEN#33=POW[2,#31+4]OR#33 #5=FIX[#5/10] END1 0は無視、5以上はエラー。 ------------- #33はフラグとして扱っているので 重複があるとビットシフトを起こす加算(+)を使うより 論理和(OR)を使った方が若干安全寄りな気がします。 おまじないみたいな物ですけど。
お礼
遅くなってすいません。 かなりレベルが高いですね。 勉強になります、有難うございます。
回答(1)さんも言われているように、「逃し」の有無や方向を示す変数は“計算が容易”な形式を選んだ方が良いです。と言ってもそれを2進数の各ビットに割り当てて(10進数の)引数で渡すとなると、今度は人間様にとって対応が分りづらくなり使い難い。 その様な場合、引数としては人間に分かりやすい形式で表現し、マクロの先頭でそれを計算し易い形式に変換すると、人間もコンピュータもお互いハッピーに。 なのでまぁ1234でも良いんですが、もう少しだけ変換し易い書式にしても良いと思う。 2進数表記のまま10110100.などと渡してしまう方法もありますが、ここは ・X方向=1,Y方向=2として、右上から反時計回りに4桁で指示 という方法を提案。 例えば下記の様な形状の場合には 2011.(Y方向|無し|X方向|X方向) と表現します。 __∩ | | | | ⊂____⊃ で、これをどんな形式に変換するとマクロで処理しやすいのか、ですが 1つは回答(1)さんの言うように2進数に変換する方法。 2進数になってると、論理演算(ANDなど)でON・OFF判定が簡単に出来るから。 他にはたった4箇所だけなので、右上を#121、左上を#122...と言うように4つの変数に分けて保持する方法も考えられます。 この方法もカウンタ変数と合わせて#[121+#1]という風に扱えるので、WHILE文の中で使いやすい。 また2進数と違って状態を多数持てるので、逃し形状のバリエーションが増えた時などに対応し易いかも知れない。 ------------------------------- 次に加工動作のルーチンについて コーナー形状が数パターンという事で、それをフラグに応じて条件分岐というのは間違いでは無いけど > (実際はX,Y方向のどちらかの逃がしのみです。I,J同時に使用することはありません。) この条件があるのであれば、基本的にポケット形状としては 「4つの直線と、4つの円弧」という構成は変化しない。 その上、円弧半径は全箇所共通、範囲も180度以下。 となると工具径補正を有効にすれば、必要なのは4つの円弧の始点・終点だけなので4x2x2=16個。 これくらいの量ならまとめて計算して#100番代などに順次放り込んでおき、最後にまとめて G41G1D#7X_Y_F#9 G3X_Y_R_(接円アプローチ) G1 (X#101) Y#102 G3 X#103 Y#104 R#33 G1 X#105 (Y#106) G3 X#107 Y#108 R#33 G1 (X#109) Y#110 G3 X#111 Y#112 R#33 G1 X#113 (Y#114) G3 X#115 Y#116 R#33 G1(X_)Y_ G3X_Y_R_(接円リトラクト) G40G1X_Y_ などとしても良いんじゃないでしょうか。 これなら多少非力なNCでも経路途中でカクカクと止まることもないし、経路の先読みも確実に出来るのでオフセットベクトル計算も正しく行える筈。 括弧の所はポケットの向きが固定なら省略可。 一応工具径補正を使わなくても似たような事は可能ですが、もう少し(多分3倍くらい)計算が増えて面倒かと。 径補正を使う時の注意点はコーナーRと工具半径との関係ですが、それは冒頭で コーナーR>工具半径+仕上げ代 を満たしていなければ コーナーR=工具半径+仕上げ代、 および 逃しは全箇所無し へとパラメータを変更してしまえば済む話。 この様にすると冒頭は計算が続くのでそこでのもたつきは発生し得るだろうけど、削ってる最中にカクつくよりは100倍マシ。 それに普通はZのアプローチ動作などが入るだろうから、その間に座標計算が終わってしまえば良いわけで... どこに計算ルーチンを置くと演算ラグが気にならなくなるかは試行錯誤してみて下さい。 > 「4つの直線と、4つの円弧」という構成は変化しない。 よくよく考えたら仕上げ代がある場合には逃しの円弧の前後にG1なりG2なりを追加しないとまずそう。 となると結局 > 一応工具径補正を使わなくても似たような事は可能ですが、 > もう少し(多分3倍くらい)計算が増えて面倒かと。 と必要な計算量は同じになっちゃうかな? と思ったけど、工具半径+仕上げ代をD99とかに入れておいて G41D99にすれば最初の方法でも致命的な問題は無さそうな気がした。 次に円弧の始点・終点の座標の求め方ですが、例えば右上について見てみると 角(右辺と上辺の交点)の座標を (X右,Y上)、 コーナーの円弧半径を R とすると ・円弧の始点 逃し形状 - X座標,Y座標 (0)逃し無 - X右, Y上-R (1)X方向 - X右, Y上-2*R (2)Y方向 - X右, Y上 ・円弧の終点 (0)逃し無 - X右-R, Y上 (1)X方向 - X右, Y上 (2)Y方向 - X右-2*R, Y上 ↑括弧内の数値はコーナー識別番号 他のコーナーも同様で、順序を抜きにすれば ポケットの頂点座標にRの0,1,2倍を加減したものという関係。 ...これ上手くすればIF文使わずに計算式だけで行けるんじゃ?
お礼
有難うございます。 レベルが高すぎて現段階では呑み込めてません、、 じっくり理解していきます。
式の評価に時間を食ってるんだと思います 逃がしありなしの サブプロを作っておく N1000:1 逃がしありX N1001:1 逃がしなしX N1010:2 逃がしありX N1011:2 逃がしなしX N1020:3 逃がしありX N1021:3 逃がしなしX N1030:4 逃がしありX N1031:4 逃がしなしX N1100:1 逃がしありY N1101:1 逃がしなしY ・ ・ ・ 評価式で X=12 Y=23 が成り立てば ジャンプテーブルで N1001 Xあり N1100 Yなし N1011 Xあり N1110 Yなし N1020 Xなし N1121 Yあり N1030 Xあり N1131 Yなし とする ただしこの場合ジャンプテーブルが 長くなるが 4^4=256パターン スムーズになるはず
補足
サブを16パターン作るという事でしょうか? IF文のORを一行に何度も使用しないで 何行かに分けるという事でしょうか?
論理演算は十進数よりもビット単位でしょうが、、、 メンドクないヌスミ方法として、コーナのXY方向を一回で円弧で結んだ方が、除去量が少なく機能面でも見栄えでも優れます。 即ち、コーナの座標を通る円弧を描く。実際にはそれより幾分か0.1でも食い込み気味にする。 | *始点 | | * 円弧中心 | 通過点*---------*----- 終点 で判ると思います。 円弧の出っ張りは少ないので、半円丸ごとでは壁を破ってしまうな時でも、強度を心配せずに使えます。 これなら殆どの場合、4隅を一々指定せず全部やってしまってよいし、論理演算しての個々指定も4個で済みます。 人間には読みづらいがコンピュータはやはり二進数が扱いやすい。8ビットを各コーナに割当てる。 二進数 十進数 加工部 00000001 = 1 1コーナのX 00000011 = 3 1 〃 XY 00001111 = 15 1,2 〃XY 00101111 = 47 1,2 〃XY +3のY 11111111 = 255 全て プログラムの骨子だけ #1:引数 #2=1 ←初期設定 N1 IF[[#1 AND #2] EQ 0] GOTO 2 ←処理無いから次へ飛ぶ 1コーナXの処理 N2 #2=#2*2 ←ビットをひとつ左へシフト IF[[#1 AND #2] NE 0] GOTO 3 1コーナYの処理 N3 #2=#2*2 IF[[#1 AND #2] NE 0] GOTO 4 この形状では工具径補正が非常に使いづらい。G4142は使わず、補正値を参照してその分軌跡をプログラムで変える方式にする。 なので、客先指定を変更するよう強力に働きかけるべきです。 スペアパーツ入れとか臍繰り用ポケットと言うなら別ですが、、、、 この形状は金型で多用します。設計初心者はマニュアル読まないとほぼ全てドカッとRを付けた絵を描く。 もし買い型でそれを発見したら、実力に?を付けます。 金型設計初心者はそうだが、一般機械屋は入れ子構造を使うのが少ないようで、ベテランでも多い。。。 >プログラムをコンパクトにしたくて 一方だけにして、他方はそれにミラーイメージを掛けるという手もあります。 ×ミラーイメージ → 座標回転 または 座標変換(+ミラーイメージ) もうひとつのテクニック。 ?カラ:#0?を使う。 #10=#0 #11=4. G01 X#10 Y#11 → G01 Y4. #0 はアドレスそのものを消し去ってしまうため、G90においてもXY両方向の動きが用意出来、変数で符号を変える操作をすると4隅ともに同じプログラムの繰返しで済ますことが出来るはずです。 マクロプログラムの極致! IF[[#4EQ1.]OR[#4EQ12.]OR[#4EQ13.]OR[#4EQ14.]OR[#4EQ123.]OR[#4EQ124.]OR[#4EQ134.]OR[#4EQ1234.]]GOTO15211 この使い方マニュアルにありましたっけ? エラーになりません? C言語などは出来るけどNCは? EQ はIFまたはWHILE命令の中で使用する条件演算子。 OR は算術演算子。 算術演算子は複数使えるが、条件演算子は1個だけではないか?
補足
>論理演算は十進数よりもビット単位でしょうが、、、 どういう意味でしょうか?(無知ですいません。) >メンドクないヌスミ方法~ 確かに簡単ですが、客先指定形状なので、、、すいません (実際はX,Y方向のどちらかの逃がしのみです。I,J同時に使用することは ありません。ただプログラムをコンパクトにしたくて、、) 複数のアドバイス有難うございます。 2進数の考え方、いろいろ応用できそうです。 >ミラーイメージ それもありですね。 >?カラ:#0?を使う。 すぐに構想できなさそうなのでじっくり考えてみます。 >この使い方マニュアルにありましたっけ? エラーになりません? 最近のFUNUCならできます。 約10年近く前の使用でもグレードによってはできました。
お礼
ご丁寧に高度な解答有難うございます。 皆さんレベルが高いですね、、 頑張って解読します。 解りやすい解答有難うございます。 ANDは2進数判定するのですね。 10進数のみと思っていました。 さっそく試してみます。
補足
>ですが、16i等ではMODは使えないと思います。 残念ながら16iもありますのでとりあえずMOD文ではなくて、 その前の追記文、FIXを用いた文例なのですが、、 仮にG65P0002I1.J1.だとすると#33=17になると思うのですが、 >IF[[#33AND1]NE1]GOTO110(右上X) G91X10. X-10. G90 N110IF[[#33AND16]NE16]GOTO120(右上X)←Y? G91Y10. Y-10. G90 この右上X・Yの判定文で#33=17との関連がよくわかりません。 (私の未熟さです。。) よろしければ解説をお願いしたいのですが、、、