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

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

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

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

Q&A

解決済

2回答

2828閲覧

processingで正三角形を複数個描画する方法

21J

総合スコア5

Processing

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

1グッド

0クリップ

投稿2021/10/22 17:15

processingを使用して正三角形の描画を行いたいです

私は現在processingを使用して複数の正三角形を描画した画像を作りたいです。
3種類(110、1525、30~40)の大きさの正三角(正確には正三角形の大きさではないですが)を角度を変えながら描画しています。三角形の個数はすべて合わせて50個としています。

###重ならないように描画
ただ描画するだけならコードが書けたのですが、正三角形同士が重なってしまいます。
そこで、正三角形同士が重ならないようにしたいです。

該当のソースコード

processing

1 2 3ArrayList<PVector> circles; 4 5void setup() { 6 size(512, 512); 7 smooth(); 8 9 frameRate(20); 10 11} 12 13void draw() { 14 15 background(255); 16 int a=int(random(1,50)); 17 int b=int(random(1,50-a)); 18 int c=50-a-b; 19 20 21 for (int n = 0; n < a; n++) { 22 int R = int(random(1,10)); 23 24 25 26 strokeWeight(1); 27 stroke(0, 0, 0); 28 fill(0); 29 pushMatrix(); 30 translate(int(random(15,490)),int(random(15,490))); 31 rotate(radians(int(random(0,90)))); 32 beginShape(); 33 for (int i = 0; i < 3; i++) { 34 vertex(R*cos(radians(360*i/3)), R*sin(radians(360*i/3))); 35 } 36 endShape(CLOSE); 37 38 popMatrix(); 39 } 40 41 for (int n = 0; n < b; n++) { 42 int R = int(random(15,25)); 43 44 45 46 strokeWeight(1); 47 stroke(0, 0, 0); 48 fill(0); 49 pushMatrix(); 50 translate(int(random(15,490)),int(random(15,490))); 51 rotate(radians(int(random(0,90)))); 52 beginShape(); 53 for (int i = 0; i < 3; i++) { 54 vertex(R*cos(radians(360*i/3)), R*sin(radians(360*i/3))); 55 } 56 endShape(CLOSE); 57 58 popMatrix(); 59 } 60 61 for (int n = 0; n < c; n++) { 62 int R = int(random(30,40)); 63 64 65 66 strokeWeight(1); 67 stroke(0, 0, 0); 68 fill(0); 69 pushMatrix(); 70 translate(int(random(15,490)),int(random(15,490))); 71 rotate(radians(int(random(0,90)))); 72 beginShape(); 73 for (int i = 0; i < 3; i++) { 74 vertex(R*cos(radians(360*i/3)), R*sin(radians(360*i/3))); 75 } 76 endShape(CLOSE); 77 78 popMatrix(); 79 80 81 82 save("F:/otamesi/data/" + frameCount +"s" + a + "m" + b +"l" + c + ".png"); 83 84 if (frameCount == 10) { // 85 noLoop(); // 86 87 88 } 89} 90}

これまで、調べたりteratailで回答して頂いたりして、円や正方形の描画は重ならないコードが書けていたのですがその際に利用していた部分を使用しても変数の数などが違う為うまくいきませんでした。
円や正方形の時の重ならないためのコードは以下です。

processing

1 while (circles.size() < sizes.length) { 2 int diameter = sizes[circles.size()]; 3 4 5 PVector c = new PVector(random(20,492), random(20,492), diameter); 6 boolean overlapping = false; 7 8 for (PVector p : circles) { 9 10 if (dist(c.x, c.y, p.x, p.y) < (c.z + p.z) / 1.9) { 11 overlapping = true; 12 break; 13 } 14 } 15 16 if (!overlapping) { 17 circles.add(c); 18 19 } 20 } 21 22 for ( 23 24 int i = 0; i < circles.size(); i++) { 25 PVector p = circles.get(i); 26 noStroke(); 27 fill(0); 28 ellipse(p.x, p.y, p.z, p.z); 29 30 }

正三角形でも重なることなく描画する方法をご教授頂けると幸いです。

TN8001👍を押しています

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

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

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

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

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

guest

回答2

0

ベストアンサー

いままで円・正方形・正三角形と来たわけです(それが最初からわかっていたら回答も違ったのですが^^;

しかしその時々でサイズが指すものが、円では直径・正方形では辺の長さ・正三角形では外接円半径とみんなバラバラです。

外接円としての当たり判定でいいようですので、サイズは外接円半径に統一したほうがわかりやすい気がします。

辺の長さと半径は公式で相互に変換できますから、どちらかがわかれば計算できます。
正多角形の外接円 - 高精度計算サイト
円に内接する正多角形 - 高精度計算サイト

延々と答えを書いても仕方がないので、上記の考えを正方形に適用した版です(↓とコンパチにしたつもり)
Processing - Processingで作成した四角形を回転させるには|teratail

正三角形版に変えてみてください。

Processing

1 2 3void setup() { 4 size(512, 512); 5 smooth(); 6 noStroke(); 7 fill(0); 8 frameRate(20); 9} 10 11void draw() { 12 background(255); 13 14 int a = int(random(0, 100)); 15 int b = int(random(0, 100 - a)); 16 int c = 100 - a - b; 17 18 FloatList sizes = new FloatList(); // 円の半径の候補 19 for (int i = 0; i < a; i++) { 20 int side = int(random(10, 20)); // 辺の長さ 21 float radius = getCircumradius(side, 4); // 正方形に外接する円の半径を取得 22 sizes.append(radius); 23 } 24 for (int i = 0; i < b; i++) { 25 int side = int(random(1, 10)); 26 float radius = getCircumradius(side, 4); 27 sizes.append(radius); 28 } 29 for (int i = 0; i < c; i++) { 30 int side = int(random(20, 39)); 31 float radius = getCircumradius(side, 4); 32 sizes.append(radius); 33 } 34 35 ArrayList<PVector> circles = getCircles(sizes); // 重ならないsizes個の円を生成 36 37 for (PVector p : circles) { 38 drawRegularPolygon(p, 4); // 円pに内接する正方形の描画 39 } 40 41 //save("F:/otamesi/data/" + frameCount +"s" + a + "m" + b + "l" + c + ".png"); 42 43 if (frameCount == 10) { 44 noLoop(); 45 println("finish"); 46 } 47} 48 49 50// 重ならないsizes個の円を生成 51ArrayList<PVector> getCircles(FloatList sizes) { 52 ArrayList<PVector> circles = new ArrayList<PVector>(); 53 54 while (circles.size() < sizes.size()) { 55 float r = sizes.get(circles.size()); 56 float x = random(r, width - r); 57 float y = random(r, height - r); 58 59 PVector c = new PVector(x, y, r); 60 61 boolean overlapping = false; 62 for (PVector p : circles) { 63 if (dist(c.x, c.y, p.x, p.y) < (c.z + p.z)) { 64 overlapping = true; 65 break; 66 } 67 } 68 69 if (!overlapping) { 70 circles.add(c); 71 } 72 } 73 74 return circles; 75} 76 77// 円pに内接する正n角形の描画 78void drawRegularPolygon(PVector p, int n) { 79 pushMatrix(); 80 81 translate(p.x, p.y); 82 rotate(random(TWO_PI)); 83 84 // 辺の長さで描画したいなら計算は可能 85 //rectMode(CENTER); 86 //square(0, 0, aaa(p.z, 4)); 87 88 beginShape(); 89 for (int i = 0; i < n; i++) { 90 float x = p.z * cos(TWO_PI / n * i); 91 float y = p.z * sin(TWO_PI / n * i); 92 vertex(x, y); 93 } 94 endShape(CLOSE); 95 96 popMatrix(); 97} 98 99 100// 正n角形に外接する円の半径を取得 101// [正多角形の外接円 - 高精度計算サイト](https://keisan.casio.jp/exec/system/1258355051) 102float getCircumradius(float a, int n) { // 辺の長さ, 頂点数 103 return a / (2 * sin(PI / n)); 104} 105 106// ↑の逆 円に内接する正n角形の辺の長さを取得(いい命名がわからない^^; 107// [円に内接する正多角形 - 高精度計算サイト](https://keisan.casio.jp/exec/system/1166416582) 108float aaa(float r, int n) { // 円の半径, 頂点数 109 return 2 * r * sin(PI / n); 110}

投稿2021/10/23 08:37

TN8001

総合スコア9326

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

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

21J

2021/10/24 06:11

ご回答ありがとうございます。 正三角形だけでなく、様々な形状にも対応できる案を考えていただきありがとうございました。
guest

0

過去の質問と本質的にはなにも変わらないのですが、幾何学的な話が難しいですか? 多分高校レベルまでの数学知識の話だと思うのですが...

そういう知識を必要としないように、ガラリと重なりを調べる原理を変えてみました。ウラ画面(PGraphics)に図形を描いてみて、実画面のコピー(の白黒反転)を描いた図形でマスクで抜いて、黒でないピクセルがあるかどうか探す、あれば重なりあり、なければ重なりなしということで。
これでもう、円だろうと四角形だろうと星型だろうとあるいはもっと変な図形でも怖くないですね。ほとんど同じ質問を繰り返さずに済むでしょう。

なお、以下のサンプルではどうにも重ならずに配置出来ない場合にはプログラムが永遠に終わらない可能性もありますが特に判定はしていません。

Processing

1DrawShape dr; 2 3void setup() { 4 size(512, 512); 5} 6 7void draw() { 8 int c=50; 9 background(255); 10 int rMin=30; 11 int rMax=40; 12 int n=0; 13 strokeWeight(1); 14 stroke(0); 15 fill(0); 16 do { 17 float R=random(rMin, rMax); 18 dr=new DrawShape(R, //図形を描くクラスインスタンス 19 random(R, width-R), random(R, height-R), //x,y 20 radians(random(0, 120)));//回転角 21 if (!overlap(dr)) {//ウラ画面で重なり判定 22 dr.draw(this.getGraphics());//実画面に描画 23 n++; 24 } 25 } while (n<c); 26 noLoop(); 27} 28 29class DrawShape { 30 float R; 31 float x, y; 32 float th; 33 34 DrawShape(float __R, float __x, float __y, float __th ) { 35 R=__R; 36 x=__x; 37 y=__y; 38 th=__th; 39 } 40 41 void draw(PGraphics pg) {//この関数で図形描画する 42 //pg.描画命令で指定画面に描画 43 pg.beginDraw(); 44 pg.translate(x, y);//座標変更系の命令はbeginDrawでクリアされるので毎回設定 45 pg.rotate(th); 46 pg.beginShape(); 47 for (int i = 0; i < 3; i++) { 48 pg.vertex(R*cos(radians(360*i/3)), R*sin(radians(360*i/3))); 49 } 50 pg.endShape(CLOSE); 51 pg.endDraw(); 52 } 53} 54 55boolean overlap(DrawShape dr) { 56 PGraphics pg=createGraphics(width, height);//ウラ画面生成 57 pg.beginDraw(); 58 pg.background(0); 59 pg.strokeWeight(1); 60 pg.stroke(255); 61 pg.fill(255); 62 pg.endDraw(); 63 dr.draw(pg); //仮想画面に図形を描く 64 65 PImage sshot=get(); //現在の実画面を取得 66 sshot.filter(INVERT); //白黒反転しておいて 67 sshot.mask(pg); //図形をマスクにして「抜く」 68 69 pg.beginDraw(); 70 pg.background(0); 71 pg.image(sshot, 0, 0); //透過情報とかいろいろある様子なので抜いた図形をウラ画面に貼り付けて確定させる 72 pg.endDraw(); 73 74 pg.loadPixels(); //画素情報取得 75 boolean ret=false; 76 for (color pix : pg.pixels) {//各画素について 77 if (pix!=color(0)) {//黒でないものがあったら重なりが有る 78 ret=true; 79 break; 80 } 81 } 82 return ret; 83}

投稿2021/10/23 02:29

thkana

総合スコア7639

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

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

21J

2021/10/24 06:13

ご回答ありがとうございます。 新しい考え方を教えていただきありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問