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

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

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

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

Q&A

解決済

3回答

1630閲覧

processingを使用して多くの正方形を描画

21J

総合スコア5

Processing

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

0グッド

0クリップ

投稿2021/06/05 20:37

processingを使用して多くの正方形を画像内に描画したいです

これまで画像内に多くの円を描写するプログラミングを使用してきました。
小(17px)、中(821px),大(22~48px)の三種類の円をそれぞれの種類ごとに個数を指定し、重ならないようにしながら描画していました。円の位置はそれぞれランダムに配置していました。
今回は円ではなく正方形を描画したかったのですが、方法が分からず質問させてもらいました。
基本的な条件などは円を描画している時と同じにしたいです。

条件としては
・正方形の個数を指定できる
・小、中、大の3種類(それぞれの大きさはある範囲内でランダム)を描画
・場所はランダムに配置される
・正方形同士は重ならない
・色は枠も内部も共に黒で指定する
・一度に多くの画像を作成

該当のソースコード

円を描写している際のコードを添付します。
大の円1個
中の円25個
小の円1個を描画した画像を400枚作った際のコードになります。

processing

1 2ArrayList<PVector> circles; // 円のデータ 3 4void setup() { 5 size(600, 600); 6 smooth(); 7 8 frameRate(20); // 1秒当たり描画数 9 10} 11 12void draw() { 13 background(255); 14 circles = new ArrayList<PVector>(); // 15 16 //データ 17 addCircle(); 18 19 20 // 円を全部描画 21 for ( 22 23 int i = 0; i < circles.size(); i++) { 24 PVector p = circles.get(i); 25 noStroke(); 26 fill(0); 27 ellipse(p.x, p.y, p.z, p.z); 28 } 29 30 31 // 画像の保存 32 save("E:/hozon/" + frameCount + ".png"); 33 34 if (frameCount == 400) { // n枚作ったら止める 35 noLoop(); // 止める 36 37 //launch("start " + sketchPath()); // Windows専用 エクスプローラでフォルダを開く 38 //exit(); // 終了 39 } 40} 41 42void addCircle() { 43 int[] sizes = { 44 int(random(22,49)), 45 int(random(8,22)), int(random(8,22)), int(random(8,22)), int(random(8,22)), int(random(8,22)), 46 int(random(8,22)), int(random(8,22)), int(random(8,22)), int(random(8,22)), int(random(8,22)), 47 int(random(8,22)), int(random(8,22)), int(random(8,22)), int(random(8,22)), int(random(8,22)), 48 int(random(8,22)), int(random(8,22)), int(random(8,22)), int(random(8,22)), int(random(8,22)), 49 int(random(8,22)), int(random(8,22)), int(random(8,22)), int(random(8,22)), int(random(8,22)), 50 int(random(1,8)), 51}; 52 53 while (circles.size() < sizes.length) { // 円のデータの個数が、必要サイズ候補数より少ない間ループ 54 // サイズを取得(配列は0始まりなので、circles.size()が0の時は0番目、circles.size()が1の時は1番目... 55 int diameter = sizes[circles.size()]; 56 57 // 3次元のベクトルのうちxyを2次元座標、zを円の直径として利用している 58 PVector c = new PVector(random(30,570), random(30,570), diameter); 59 boolean overlapping = false; 60 61 for (PVector p : circles) { 62 // zは直径なので理屈的には割る2 くっついて見えるのがまずい場合は、少し足すなりなんなり 63 if (dist(c.x, c.y, p.x, p.y) < (c.z + p.z) / 2) { 64 overlapping = true; 65 break; 66 } 67 } 68 69 if (!overlapping) { 70 circles.add(c); 71 } 72 } 73}

ご存じの方がおられたらお力添えお願いいたします。

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

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

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

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

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

TN8001

2021/06/05 22:00

正方形なら辺の長さが同じですから、円の場合と同様の手法(xyを座標・zを辺の長さとして利用)が使えます。 であれば問題は重なり判定のコードだけです。 if (dist(c.x, c.y, p.x, p.y) < (c.z + p.z) / 2) この条件を変えるだけですが、どの程度調べたのでしょうか? 以前の質問のコードそのままで、丸投げと取られます。 注)正確には当然ellipseをrectに変更と、rectMode(CENTER)の追加も必要ですが^^;
thkana

2021/06/05 23:47

> ellipseをrectに変更 ねぇ、みんなsquare()とかcircle()って使わないの?
TN8001

2021/06/06 04:27

w 恥ずかしながら当時は知らなかったのです^^; 引数の数が変わるため、変に混乱させないようにrectと書きました。 今手元に準備中のコードではsquareを使用しています^^
21J

2021/06/06 10:23

確かに丸投げと捉えられるような質問であったと反省しています。 切れたり、重なってしまったりという不具合があったのですがrectMode(CENTER)を入れると解決しました。 ありがとうございます。
TN8001

2021/06/06 10:36

> rectMode(CENTER)を入れると解決しました。 自力で解決されましたか。おめでとうございます^^ であれば、自己回答で閉じていただいて結構です。 解決コードも載せれば、もしかしたら誰かの役に立つかもしれません。
TN8001

2021/06/06 10:45

> 解決コードも載せれば、もしかしたら誰かの役に立つかもしれません。 あるいは間違っている場合、誰かから突っ込みが入ります^^; rectModeを変えても円の当たり判定のままでは重なりますよ。
guest

回答3

0

画を描いてみたら
画
重なる(重ならない)条件の式がわかりませんか?


返信について...

「重なりさえしなければいい」のならdist(c.x, c.y, p.x, p.y) < (c.z + p.z) *1.42/ 2でも構いませんけれど、重ならずにもっと近くに配置できるケースを排除しています。

画2
この図において、
dist(c.x, c.y, p.x, p.y) は(c.z+p.z)/2 になるのはわかりますね。
(c.z + p.z)/2 < (c.z + p.z) *1.42/ 2
は真ですが、重なりません。

投稿2021/06/23 11:35

編集2021/06/30 22:52
thkana

総合スコア7610

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

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

21J

2021/06/30 10:44

返信遅くなってしまい申し訳ありません。 正方形なので中心位置から辺までの長さではなく、対角線をとらないと重なってしまうというので重なっていたということですか? if (dist(c.x, c.y, p.x, p.y) < (c.z + p.z) *1.42/ 2) { overlapping = true; break; のように変更したら重ならなくなりました。
thkana

2021/06/30 23:02

正方形(長方形)なので対角線ではなく、中心位置から辺までの長さで考えるべき、ということです。
guest

0

まずは円を描くところを単純に正方形に置き換えてみましょう。
そのうえで、どういう不具合があるか、それをどうしたいのか、というのをそのコードとともに聞いていただけるとよろしいかと

投稿2021/06/05 21:40

y_waiwai

総合スコア87719

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

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

21J

2021/06/06 10:26

単純にcirclesをrectに変えただけでは切れたり重なったりが起きてしまっていたので質問させてもらっていました。 rectMode(CENTER)が抜けていたようです。 質問の仕方に不備があったと反省しております。
y_waiwai

2021/06/06 10:56

ならそのやったこと、起きたことを質問に書きましょう。 なぜこの質問に回答がつかないのかを考えてみては。
guest

0

自己解決

circleをrectに変更しました。
重なりの式”if (dist(c.x, c.y, p.x, p.y) < (c.z + p.z) / 2.0)”に問題があるようで重なってしまったので数値を小さくしました。
正しい改善方法なのかはわからないですが、とりあえず2.0を1.5にすると重なりは解消できました。

processing

1 2 3ArrayList<PVector> rect; // 円のデータ 4 5void setup() { 6 size(512, 512); 7 smooth(); 8 9 frameRate(20); // 1秒当たり描画数 10 11} 12 13void draw() { 14 background(255); 15 rect = new ArrayList<PVector>(); // 16 17 //データ 18 addrect(); 19 20 21 // 円を全部描画 22 for ( 23 24 int i = 0; i < rect.size(); i++) { 25 PVector p = rect.get(i); 26 noStroke(); 27 fill(0); 28 rect(p.x, p.y, p.z, p.z); 29 rectMode(CENTER); 30 } 31 32 33 // 画像の保存 34 save("E:/hozon/" + frameCount + ".png"); 35 36 if (frameCount == 100) { // n枚作ったら止める 37 noLoop(); // 止める 38 39 //launch("start " + sketchPath()); // Windows専用 エクスプローラでフォルダを開く 40 //exit(); // 終了 41 } 42} 43 44void addrect() { 45 int[] sizes = { 46 47 int(random(4,15)),int(random(4,15)),int(random(4,15)),int(random(4,15)),int(random(4,15)), 48 int(random(4,15)),int(random(4,15)),int(random(4,15)),int(random(4,15)),int(random(4,15)), 49 int(random(4,15)),int(random(4,15)),int(random(4,15)),int(random(4,15)),int(random(4,15)), 50 int(random(4,15)),int(random(4,15)),int(random(4,15)),int(random(4,15)),int(random(4,15)),int(random(4,15)), 51 int(random(1,4)), int(random(1,4)),int(random(1,4)),int(random(1,4)),int(random(1,4)), 52 int(random(1,4)),int(random(1,4)),int(random(1,4)),int(random(1,4)),int(random(1,4)), 53}; 54 55 while (rect.size() < sizes.length) { // 円のデータの個数が、必要サイズ候補数より少ない間ループ 56 // サイズを取得(配列は0始まりなので、circles.size()が0の時は0番目、circles.size()が1の時は1番目... 57 int diameter = sizes[rect.size()]; 58 59 // 3次元のベクトルのうちxyを2次元座標、zを円の直径として利用している 60 PVector c = new PVector(random(25,487), random(25,487), diameter); 61 boolean overlapping = false; 62 63 for (PVector p : rect) { 64 // zは直径なので理屈的には割る2 くっついて見えるのがまずい場合は、少し足すなりなんなり 65 if (dist(c.x, c.y, p.x, p.y) < (c.z + p.z) / 1.5) { 66 overlapping = true; 67 break; 68 } 69 } 70 71 if (!overlapping) { 72 rect.add(c); 73 } 74 } 75}

投稿2021/06/23 10:05

21J

総合スコア5

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

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

thkana

2021/06/23 10:50

> 正しい改善方法なのかはわからないですが 正しくないですね。
thkana

2021/06/23 11:22 編集

(正しくない例) size(200,200); rectMode(CENTER); PVector c=new PVector(60,60,100); float d=(100+100)/1.5/sqrt(2)+61; PVector p=new PVector(d,d,100); float d1=dist(c.x,c.y,p.x,p.y); println(d1); println((c.z+p.z)/1.5); square(c.x,c.y,c.z); square(p.x,p.y,p.z);
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問