回答編集履歴

3

ベジェ円 java コード追加

2024/05/21 12:19

投稿

jimbe
jimbe

スコア13168

test CHANGED
@@ -93,3 +93,144 @@
93
93
  [ベジェ曲線を使って 円を描画する Java2D](https://blog.ideastorage.net/posts/kotlin-java2d-bezier/)
94
94
 
95
95
  1/4 円を GeneralPath の curveTo で書いているので、そのパラメータの点の位置をずらすような形にすればうねうねする…かもしれません。
96
+ kotlin だったので java に直しました。
97
+ ```java
98
+ import java.awt.Color;
99
+ import java.awt.Graphics2D;
100
+ import java.awt.geom.GeneralPath;
101
+ import java.awt.geom.Point2D;
102
+ import java.awt.image.BufferedImage;
103
+ import java.io.File;
104
+ import java.io.IOException;
105
+ import java.util.Arrays;
106
+ import java.util.List;
107
+
108
+ import javax.imageio.ImageIO;
109
+
110
+ class BezierCircle {
111
+ private static class MatrixUtils {
112
+ static float[] times(float[] a, float[] b) {
113
+ return new float[] {
114
+ a[0]*b[0] + a[1]*b[3] + a[2]*b[6],
115
+ a[0]*b[1] + a[1]*b[4] + a[2]*b[7],
116
+ a[0]*b[2] + a[1]*b[5] + a[2]*b[8],
117
+
118
+ a[0+3]*b[0] + a[1+3]*b[3] + a[2+3]*b[6],
119
+ a[0+3]*b[1] + a[1+3]*b[4] + a[2+3]*b[7],
120
+ a[0+3]*b[2] + a[1+3]*b[5] + a[2+3]*b[8],
121
+
122
+ a[0+3*2]*b[0] + a[1+3*2]*b[3] + a[2+3*2]*b[6],
123
+ a[0+3*2]*b[1] + a[1+3*2]*b[4] + a[2+3*2]*b[7],
124
+ a[0+3*2]*b[2] + a[1+3*2]*b[5] + a[2+3*2]*b[8]
125
+ };
126
+ }
127
+
128
+ static float[] times(float[] a, float[] b, float[] c) { return times( a, times(b, c) ); }
129
+ static float[] times(float[] a, float[] b, float[] c, float[] d) { return times( a, times(b, times(c, d)) ); }
130
+
131
+ static float[] transform(float[] a, float x, float y) {
132
+ float[] b = new float[] { x, y, 1f };
133
+
134
+ float c00 = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
135
+ float c10 = a[0 + 3] * b[0] + a[1 + 3] * b[1] + a[2 + 3] * b[2];
136
+ float c20 = a[0 + 6] * b[0] + a[1 + 6] * b[1] + a[2 + 6] * b[2];
137
+
138
+ return new float[] { c00, c10, c20 };
139
+ }
140
+
141
+ static Point2D.Float transform(float[] a, Point2D.Float pt) {
142
+ float[] array = transform(a, pt.x, pt.y);
143
+ return new Point2D.Float(array[0], array[1]);
144
+ }
145
+ }
146
+
147
+ private static double toRadian(double degree) { return degree * Math.PI/180f; }
148
+
149
+ // 原点に並行移動して、degree度分回転、元の位置へ並行移動する matrixValues を生成:
150
+ private static float[] toMatrixValues(double degree) {
151
+ double radian = toRadian(degree);
152
+
153
+ float[] matrixValues0 = new float[] {
154
+ 1f, 0f, -50f,
155
+ 0f, 1f, -50f,
156
+ 0f, 0f, 1f };
157
+
158
+ float[] matrixValues1 = new float[] {
159
+ (float)Math.cos(radian), (float)-Math.sin(radian), 0f,
160
+ (float)Math.sin(radian), (float) Math.cos(radian), 0f,
161
+ 0f, 0f, 1f };
162
+
163
+ float[] matrixValues2 = new float[] {
164
+ 1f, 0f, 50f,
165
+ 0f, 1f, 50f,
166
+ 0f, 0f, 1f };
167
+
168
+ return MatrixUtils.times(matrixValues2, matrixValues1, matrixValues0);
169
+ };
170
+
171
+ // 回転して並行移動する matrixValues を生成:
172
+ static float[] toMatrixValuesWithTranslation(double degree, float dx, float dy) {
173
+ float[] matrixValues = new float[] {
174
+ 1f, 0f, dx,
175
+ 0f, 1f, dy,
176
+ 0f, 0f, 1f };
177
+
178
+ return MatrixUtils.times( matrixValues, toMatrixValues(degree) );
179
+ }
180
+
181
+ public static void main(String[] args) throws IOException {
182
+ System.setProperty("java.awt.headless", "true");
183
+
184
+ // 200x200 のキャンバスを作成:
185
+ int w = 200;
186
+ int h = 200;
187
+
188
+ BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
189
+
190
+ Graphics2D g = (Graphics2D)img.getGraphics();
191
+ g.setColor(Color.WHITE);
192
+ g.fillRect(0, 0, w, h);
193
+
194
+ // 中心が (100,100) 半径 R=100 の円弧 (左上1/4) を描画するための点の計算:
195
+ float M = (4f / 3f * ((float)Math.sqrt(2d)-1f)); /// 円をベジェで描くためのマジックナンバー
196
+ float R = 100f;
197
+ float RM = R*M;
198
+
199
+ Point2D.Float startPt = new Point2D.Float(0f, R);
200
+ Point2D.Float controlPt1 = new Point2D.Float(0f, R-RM);
201
+ Point2D.Float controlPt2 = new Point2D.Float(R-RM, 0f);
202
+ Point2D.Float stopPt = new Point2D.Float(R, 0f);
203
+
204
+ List<Point2D.Float> ptList = Arrays.asList(startPt, controlPt1, controlPt2, stopPt);
205
+
206
+ // 残りの 3つの円弧は、今作成した点をベースに回転と並行移動を使って作成:
207
+
208
+ float[] matrixValues1 = toMatrixValuesWithTranslation(90*1d, 100f, 0f);
209
+ float[] matrixValues2 = toMatrixValuesWithTranslation(90*2d, 100f, 100f);
210
+ float[] matrixValues3 = toMatrixValuesWithTranslation(90*3d, 0f, 100f);
211
+
212
+ List<Point2D.Float> ptList1 = ptList.stream().map(it -> MatrixUtils.transform(matrixValues1, it)).toList();
213
+ List<Point2D.Float> ptList2 = ptList.stream().map(it -> MatrixUtils.transform(matrixValues2, it)).toList();
214
+ List<Point2D.Float> ptList3 = ptList.stream().map(it -> MatrixUtils.transform(matrixValues3, it)).toList();
215
+
216
+ // パスを使って円を描画:
217
+ GeneralPath path = new GeneralPath();
218
+
219
+ Arrays.asList(ptList, ptList1, ptList2, ptList3).stream().forEach(it -> {
220
+ path.moveTo(it.get(0).x, it.get(0).y);
221
+ path.curveTo(
222
+ it.get(1).x, it.get(1).y,
223
+ it.get(2).x, it.get(2).y,
224
+ it.get(3).x, it.get(3).y);
225
+ });
226
+
227
+ g.setColor(Color.BLACK);
228
+ g.draw(path);
229
+
230
+ // PNGとしてファイルに保存:
231
+ File pngFile = new File("circle.png");
232
+ ImageIO.write(img, "PNG", pngFile);
233
+ }
234
+ }
235
+ ```
236
+ ![circle.png](https://ddjkaamml8q8x.cloudfront.net/questions/2024-05-21/6eb0e43a-2ba6-4c3d-b69e-a9df57cab248.png)

2

追記

2024/05/20 12:29

投稿

jimbe
jimbe

スコア13168

test CHANGED
@@ -88,3 +88,8 @@
88
88
  }
89
89
  }
90
90
  ```
91
+ 何か弄る元になるものは無いかなと探すと
92
+
93
+ [ベジェ曲線を使って 円を描画する Java2D](https://blog.ideastorage.net/posts/kotlin-java2d-bezier/)
94
+
95
+ 1/4 円を GeneralPath の curveTo で書いているので、そのパラメータの点の位置をずらすような形にすればうねうねする…かもしれません。

1

修正

2024/05/20 11:27

投稿

jimbe
jimbe

スコア13168

test CHANGED
@@ -1,4 +1,6 @@
1
1
  CirclePanel 部分だけで動かしてみました。
2
+ で、コード通りならこうなるワケですけども、HTML は角丸を変えることでうねうねしていますがそれが全くコードに無いですね。
3
+ 理想通りにならないというのは、角丸を色々変える方法を知りたいということになるのでしょうか。
2
4
  ```java
3
5
  import java.awt.*;
4
6
  import java.awt.event.MouseAdapter;