質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Processing

Processingは、オープンソースプロジェクトによるCGのためのプログラミング言語です。Javaをベースにしており、グラフィック機能に特化しています。イメージの生成やアニメーションなど、視覚的なフィードバックを簡単に得ることが可能です。

Q&A

解決済

3回答

594閲覧

ループ処理での負の値の剰余について

P5_USER

総合スコア73

Processing

Processingは、オープンソースプロジェクトによるCGのためのプログラミング言語です。Javaをベースにしており、グラフィック機能に特化しています。イメージの生成やアニメーションなど、視覚的なフィードバックを簡単に得ることが可能です。

0グッド

0クリップ

投稿2018/03/05 10:16

編集2018/03/06 01:36

いつもお世話になっています。

前提・実現したいこと

負の値を持つときでも、剰余(%)でループ処理ができるようにしたい。
(例)psiが-90の時に目盛で27を示す。

発生している問題・エラーメッセージ

psiが負の値を持つとき、剰余(%)演算がされない。

該当のソースコード

tweakモードでpsiをスライドしてもらえると、問題への理解が早まると思います。

processing

1import hypermedia.net.*; 2UDP udp; 3 4PFont Font;//HUDフォント 5float newX = 0, newY = 0; 6float bank; 7float font_size_small; 8float font_size_large; 9 10float theta = 0;//ピッチ各 11float phi = 0;//バンク角 12float psi = 0;//方位角 13 14void setup() 15{ 16 size(displayWidth, displayHeight); 17 Font = loadFont("Verdana-48.vlw"); 18 strokeWeight(displayHeight/350); 19 20 //udp = new UDP (this, 60000); 21 //udp.listen(true); 22} 23 24void draw() 25{ 26 font_size_small = displayHeight/40; 27 font_size_large = displayHeight/30; 28 textFont(Font, font_size_small); 29 30 theta = 0; 31 phi = 0; 32 psi = 0; 33 34 bank = radians(-phi); 35 36 background(0); 37 fill(0, 255, 0); 38 smooth(); 39 horizon_region(); 40}
void horizon_region() { int[] pitch_label_str_plus = { 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90};//ピッチ角がプラスのラベル int[] pitch_label_str_minus = {-5, -10, -15, -20, -25, -30, -35, -40, -45, -50, -55, -60, -65, -70, -75, -80, -85, -90};//ピッチ角がマイナスのラベル int pitch_num = pitch_label_str_plus.length;//表示するラベルの数 float pitch_scale_length_half = displayHeight * 3.00;//片方のピッチラベルの表示する長さ float pitch_num_distance = pitch_scale_length_half / pitch_num;//ラベルの座標的な間隔 float pitch_num_plus_exist;//ピッチ角が正のラベルの存在するy座標 float pitch_num_minus_exist;//ピッチ角が負のラベルの存在するy座標; float pitch_num_interval = displayWidth * 0.15;//数字ラベルの存在するx座標 float line_outer = displayWidth * 0.145;//線の外側端点x座標 float line_inner = displayWidth * 0.075;//線の内側端点x座標 float y = map(theta, -90, 90, -pitch_scale_length_half, pitch_scale_length_half); translate(displayWidth / 2, displayHeight / 2); rotate(bank); line(-displayWidth/14, 0, displayWidth/14, 0); line(-displayWidth/14, 0, -displayWidth/10, displayHeight/20); line(-displayWidth/14, 0, -displayWidth/10, -displayHeight/20); line(displayWidth/14, 0, displayWidth/10, displayHeight/20); line(displayWidth/14, 0, displayWidth/10, -displayHeight/20); for (int i=0; i <= pitch_num-1; i++) { pitch_num_plus_exist = - (1 + i) * pitch_num_distance + font_size_small + y; textAlign(LEFT); text(nf(pitch_label_str_plus[i], 2), pitch_num_interval, pitch_num_plus_exist); textAlign(RIGHT); text(nf(pitch_label_str_plus[i], 2), -pitch_num_interval, pitch_num_plus_exist); line(line_inner, pitch_num_plus_exist - font_size_small, line_outer, pitch_num_plus_exist - font_size_small); line(-line_inner, pitch_num_plus_exist - font_size_small, -line_outer, pitch_num_plus_exist - font_size_small); line(line_outer, pitch_num_plus_exist, line_outer, pitch_num_plus_exist - font_size_small); line(-line_outer, pitch_num_plus_exist, -line_outer, pitch_num_plus_exist - font_size_small); } for (int i=0; i <= pitch_num-1; i++) { pitch_num_minus_exist = (1 + i) * pitch_num_distance + y; textAlign(LEFT); text(nf(pitch_label_str_minus[i], 2), pitch_num_interval, pitch_num_minus_exist); textAlign(RIGHT); text(nf(pitch_label_str_minus[i], 2), -pitch_num_interval, pitch_num_minus_exist); line(line_inner, pitch_num_minus_exist, line_outer, pitch_num_minus_exist); line(-line_inner, pitch_num_minus_exist, -line_outer, pitch_num_minus_exist); line(line_outer, pitch_num_minus_exist, line_outer, pitch_num_minus_exist - font_size_small); line(-line_outer, pitch_num_minus_exist, -line_outer, pitch_num_minus_exist - font_size_small); } rotate(-bank); translate(-displayWidth / 2, -displayHeight / 2); int[] azimuth_label_str = {34, 35, 36, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 1, 2};//方位を数字で格納するための配列 int azi_num = azimuth_label_str.length; float azi_scale_length = displayWidth * 15.0; float azi_num_distance = azi_scale_length / azi_num; float azi_num_exist; float scale_sub_exist; float x = -map(psi, 0, 360, (0) * azi_num_distance, (36) * azi_num_distance); translate(displayWidth / 2, displayHeight / 2); rotate(bank); if (psi >= 0) { x = x%(36 * azi_num_distance); } if (psi < 0) { //ココ x = x%(36 * azi_num_distance);//仮 } noFill(); stroke(0, 255, 0); textAlign(CENTER); for (int i = 0; i <= azi_num - 1; i++) { azi_num_exist = x + (i-2) * azi_num_distance; scale_sub_exist = azi_num_exist + azi_num_distance / 2; text(nf(azimuth_label_str[i], 2), azi_num_exist, -displayHeight/30 + y);//数字 line(azi_num_exist, y, azi_num_exist, -displayHeight/40 + y);//大目盛 line(scale_sub_exist, y, scale_sub_exist, -displayHeight/70 + y);//小目盛 line(azi_num_exist, y, x + (i-3) * azi_num_distance, y); } rotate(-bank); translate(-displayWidth/2, -displayHeight/2); }

試したこと

xをabs(x)にしたり、←当然ダメ
xを-xにしたり、←同じくダメ
してみましたが、どうすれば、(例えば)psiが-90の時に目盛で27を示してくれるのでしょうか。

補足情報(FW/ツールのバージョンなど)

processing 3.3.6

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2018/03/05 10:20

どういう計算をしたいんでしょうか?ソース読むのがめんどいです
P5_USER

2018/03/05 10:54 編集

現在、方位計を作成しています。外部入力をpsiという変数で受け止めています。ただし、画面の中での描写はピクセル数なので、psiの値をそのまま入れてしまっては駄目で、map()を使用して幅をpsiの値を画面の値に対応させています。その時の返り値がxという変数に格納されていて、xの値で目盛の表示する場所をコントロールしています。今回、psiが360以上でも、例えばpsi=370の時は剰余の関係から画面の目盛は10を示していてくれていますが、psiが負の値をとったときに剰余の演算子が機能しなくなっている状況です。
y_waiwai

2018/03/05 10:50

360の剰余を求めたいという話ですか?それでphiのとり得る最小値はいくらでしょうか
y_waiwai

2018/03/05 10:53

あ、phiじゃなくpsiですか
P5_USER

2018/03/05 10:54

申し訳ありません。こちらのミスでphiをpsiと書いていました。>360の剰余を求めたいという話ですか?:その通りです。psiのとり得る値は未知数です。psiの値等は運動計算模擬PCからの出力となっていて、中身が分からないためです。
guest

回答3

0

自己解決

ラベルの数を大幅に増やし、マップの幅を変更しました。
また,KSwordOfHasteさんの回答にある2行目を使いうことで、本問題を解決できました。

ただし、あまり綺麗な書き方ではないので,今後もブラッシュアップですね......

processing

1int[] azimuth_label_str = {35, 36, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 1, 2};//方位を数字で格納するための配列 2 int azi_num = azimuth_label_str.length; 3 float azi_scale_length = displayWidth * 20.0; 4 float azi_num_distance = azi_scale_length / azi_num; 5 float azi_num_exist; 6 float scale_sub_exist; 7 8 float x = -map(psi, -360, 360, (-36) * azi_num_distance, (36) * azi_num_distance); 9 translate(displayWidth / 2, displayHeight / 2); 10 11 rotate(bank); 12 13 if (psi >= 0) 14 { 15 x = x%(36 * azi_num_distance); 16 } else if (psi < 0) 17 { 18 float divisor = 36 * azi_num_distance;//除数 19 x = ((x%divisor)+divisor)%divisor; 20 } 21 22 noFill(); 23 stroke(0, 255, 0); 24 25 textAlign(CENTER); 26 27 for (int i = 0; i <= azi_num - 1; i++) 28 { 29 azi_num_exist = x + (i-37) * azi_num_distance; 30 scale_sub_exist = azi_num_exist + azi_num_distance / 2; 31 32 text(nf(azimuth_label_str[i], 2), azi_num_exist, -displayHeight/30 + y);//数字 33 line(azi_num_exist, y, azi_num_exist, -displayHeight/40 + y);//大目盛 34 line(scale_sub_exist, y, scale_sub_exist, -displayHeight/70 + y);//小目盛 35 line(azi_num_exist, y, x + i * azi_num_distance, y); 36 } 37 38 rotate(-bank); 39 40 translate(-displayWidth/2, -displayHeight/2);

投稿2018/03/06 02:05

P5_USER

総合スコア73

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

Javaの%演算子は

10 % 3 ==> 1
-10 % 3 ==> -1

になるという仕様です。これが

-10 % 3 ==> 2

となってくれる方が嬉しい場合がよくあります。本件もそういうことが関係しているのではないかと思います。

いくつか対処法が考えられますが、第二オペランドは常に正数と仮定できることが多いでしょうから・・・

Java

1divisor = 3; // 除数 2mod = ((x % divisor) + divisor) % divisor; // いまひとつ簡潔さに欠ける・・・ 3mod = x - floor(x / divisor) * divisor; // せめてこれくらい?

投稿2018/03/05 10:59

KSwordOfHaste

総合スコア18392

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KSwordOfHaste

2018/03/05 11:02

なんだか違う話だったかしら・・・><
P5_USER

2018/03/05 11:09

KSwordOfHasteさん ありがとうございます。 オペランドについては初めて耳にしました。 先ず、オペランドについて勉強してみます。
KSwordOfHaste

2018/03/05 11:47 編集

単なる用語です。a+bのような式で、文法的に'+'を演算子(operator)、aやbのことを'+'演算子の対象となる値という意味でオペランドといったりするという程度の用語でそれほど深い意味があるわけではないです。 本件では第二オペランドなんていわずに単に「除数」と言えば充分でした。失礼しました。
P5_USER

2018/03/06 01:33

if (psi < 0) { float divisor = 36 * azi_num_distance;//除数 //xx = -(abs(x)%(36 * azi_num_distance)); xx = ((x%divisor)+divisor)%divisor; //xx = x - floor(x / divisor) * divisor; } にしてみましたが、ダメでした......
KSwordOfHaste

2018/03/06 02:08

えーと・・・話を単純にする方がよいと思います。閲覧者は必ずしもあなたのコードをProcessingにコピペして動かすとは限りません。かなり長いプログラムですので面倒です。それを期待するのではなく、 「azi_num_distacneがA, xがBのとき、Cが期待なのだが、Dになってしまう」 というようにA, B, C, Dの具体的な値の例を書いた方が答えやすいですよ?
P5_USER

2018/03/06 02:12

分かりました。 以後気を付けます。
guest

0

たとえば、方位360度を指すとして、
y=(x+(360*2))%360; ただし、x>-720 の場合
で方位が出ますな。

ってこれでいいのかな?

投稿2018/03/05 10:56

y_waiwai

総合スコア87719

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

P5_USER

2018/03/05 10:59

y_waiwaiさん ありがとうございます。 そうですね、xが有限小の場合は360に対して『現実的』な値を乗じて剰余演算子を働かせるべきですよね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問