teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

7

コードを訂正

2018/10/01 05:04

投稿

KSwordOfHaste
KSwordOfHaste

スコア18404

answer CHANGED
@@ -72,6 +72,9 @@
72
72
  ---
73
73
  追記2:
74
74
  あまりきれいとは言えないかもしれませんが、一応前述の問題をクリアできそうなコードを挙げておきます。
75
+ 追記3:
76
+ 何度もすみませんが、さらに間違いに気づいたので追記2のコードを訂正します。追記2のコードでは(0,0)->(1,5)などの線分を描画すると余計な画素までプロットされてしまってました orz
77
+
75
78
  ```C
76
79
  int dx = (x1 - x0) * 2; // 必ず2で割り切れるようにする
77
80
  int dy = (y1 - y0) * 2; // 同上
@@ -80,18 +83,18 @@
80
83
  int delta_x_mid = dy / 2;
81
84
  int delta_x = delta_x_mid;
82
85
  for (;;) {
83
- plotPixel(x, y);
86
+ plotPixel(x, y); // ... この画素を「主画素」ということにします
84
87
  if (y == y1) break;
85
88
  if (y != y0) {
86
89
  // y0 < y < y1であるような点でのみ左右の画素を追加すべきか判定
87
90
  if (delta_x < delta_x_mid) {
88
- // yが0.5だけ小さい座標で線分がちょうど画素位置しないことを確認
91
+ // yが0.5だけ小さい位置のx座標を吟味し主画素の左追加すべきか判定
89
- if (delta_x - dx / 2 != 0) {
92
+ if (delta_x - dx / 2 < 0) { //追記2では!=0となっていました。
90
93
  plotPixel(x - 1, y);
91
94
  }
92
95
  } else if (delta_x > delta_x_mid) {
93
- // yが0.5だけ大きい座標で線分がちょうど画素位置しないことを確認
96
+ // yが0.5だけ大きい位置のx座標を吟味し主画素の右追加すべきか判定
94
- if (delta_x + dx / 2 != dy) {
97
+ if (delta_x + dx / 2 > dy) { //追記2では!=dyとなっていました
95
98
  plotPixel(x + 1, y);
96
99
  }
97
100
  }

6

誤記訂正

2018/10/01 05:04

投稿

KSwordOfHaste
KSwordOfHaste

スコア18404

answer CHANGED
@@ -7,13 +7,12 @@
7
7
  (A) 本来の線分が通過する画素は必ずプロットする
8
8
  (B) 線分の太さをなるべく細くする
9
9
 
10
- という背反する要件のうち通常は(B)の方が重視される気がするのです・・・自はないですが。
10
+ という背反する要件のうち通常は(B)の方が重視される気がするのです・・・自はないですが。
11
11
 
12
-
13
12
  ----
14
13
  それはともかく・・・残念ながら自分は(A)の要件を満たすアルゴリズムとしてポピュラーなものがあるかどうか知りません。しかしながらこれはプレゼンハムのアルゴリズムの考え方をそのまま踏襲して若干手を入れればできそうな気もします。
15
14
 
16
- 仮にご質問の線分の例でいうとx方向の差分が2, y方向の差分が3なのでy座標を1ずつずらしながらx座標を1増やすかどうかその都度判断しますね?プレゼンハムのアルゴリズム(の改良版かな?)の要点はこのずらすかどうかの判定を微分法の素朴なシミュレーションによりデジタル的に行う点です。複雑さを避けるため条件つきの限定的なアルゴリズムを書くと・・・
15
+ ご質問の線分の例でいうとx方向の差分が2, y方向の差分が3なのでy座標を1ずつずらしながらx座標を1増やすかどうかその都度判断しますね?プレゼンハムのアルゴリズム(の改良版かな?)の要点はこのずらすかどうかの判定を微分法の素朴なシミュレーションによりデジタル的に行う点です。複雑さを避けるため条件つきの限定的なアルゴリズムを書くと・・・
17
16
 
18
17
  ```C
19
18
  // 始点の座標はx0, y0, 終点はx1, y1とする

5

改善コードを追記

2018/10/01 03:33

投稿

KSwordOfHaste
KSwordOfHaste

スコア18404

answer CHANGED
@@ -68,4 +68,41 @@
68
68
  ※: 「それっぽい」なんてアバウトな言い方をしましたがそれは「厳密に検証してないのでひょっとしたら本来の線分が通過する画素をプロットしそこねる場合もあるかも知れない」と思ったからです。すみませんが少々面倒だったので検証を省いちゃいました。不備があったらすみません。一つのアイデアとしてみていただければと思います。
69
69
 
70
70
  ==>追記:傾きを変えて複数の線分の描画を観察してみたところ、案の定、要件を満たさないかも知れないケース(実行例の図の左から2番目の線分)があることに気づきました。
71
- これが許容できるならよいのですが、まずいならもっと境界条件等を慎重に検討する必要がありそうです。修正方法がわかったら回答へ反映したいと思いますが・・・思いつかないかも知れません。その時はゴメンナサイ
71
+ これが許容できるならよいのですが、まずいならもっと境界条件等を慎重に検討する必要がありそうです。修正方法がわかったら回答へ反映したいと思いますが・・・思いつかないかも知れません。その時はゴメンナサイ
72
+
73
+ ---
74
+ 追記2:
75
+ あまりきれいとは言えないかもしれませんが、一応前述の問題をクリアできそうなコードを挙げておきます。
76
+ ```C
77
+ int dx = (x1 - x0) * 2; // 必ず2で割り切れるようにする
78
+ int dy = (y1 - y0) * 2; // 同上
79
+ int x = x0;
80
+ int y = y0;
81
+ int delta_x_mid = dy / 2;
82
+ int delta_x = delta_x_mid;
83
+ for (;;) {
84
+ plotPixel(x, y);
85
+ if (y == y1) break;
86
+ if (y != y0) {
87
+ // y0 < y < y1であるような点でのみ左右の画素を追加すべきか判定
88
+ if (delta_x < delta_x_mid) {
89
+ // yが0.5だけ小さい座標で線分がちょうど画素間に位置しないことを確認
90
+ if (delta_x - dx / 2 != 0) {
91
+ plotPixel(x - 1, y);
92
+ }
93
+ } else if (delta_x > delta_x_mid) {
94
+ // yが0.5だけ大きい座標で線分がちょうど画素間に位置しないことを確認
95
+ if (delta_x + dx / 2 != dy) {
96
+ plotPixel(x + 1, y);
97
+ }
98
+ }
99
+ }
100
+ y++;
101
+ delta_x += dx;
102
+ if (delta_x >= dy) {
103
+ delta_x -= dy;
104
+ x++;
105
+ }
106
+ }
107
+ ```
108
+ ![イメージ説明](abe69cfa37b26e05aab9d71b712c22f3.png)

4

説明での論理の誤りを訂正

2018/09/30 18:24

投稿

KSwordOfHaste
KSwordOfHaste

スコア18404

answer CHANGED
@@ -24,7 +24,7 @@
24
24
  int dy = y1 - y0; // 前提により必ず正の値
25
25
  int x = x0;
26
26
  int y = y0;
27
- int delta_x_mid = dx / 2;
27
+ int delta_x_mid = dy / 2; // 最初のコードではdx/2としてましたがこちらが適切だと思います
28
28
  int delta_x = delta_x_mid;
29
29
  for (;;) {
30
30
  plotPixel(x, y);
@@ -38,14 +38,14 @@
38
38
  }
39
39
  }
40
40
  ```
41
- こんな感じですね。ここでdelta_xの意味を考えてみると、一つの画素の幅が(便宜上)dxだとしたときの本来の線分がそのy座標でのxの本来の座標を近似する値といえます。つまり
41
+ こんな感じですね。ここでdelta_xの意味を考えてみると、一つの画素の幅が(便宜上)~~dx(間違えました!)~~dyだとしたときの本来の線分がそのy座標でのxの本来の座標を近似する値といえます。つまり
42
42
  ```text
43
43
  +-----+ +-----+ +-----+
44
44
  | | | | | |
45
45
  * | | * | | *
46
46
  | | | | | |
47
47
  +-----+ +-----+ +-----+
48
- delta_x 0 dx/2 dx-1
48
+ delta_x 0 dy/2 dy-1
49
49
  ```
50
50
  図の`*`が本来の線分が通過する点のあたりとみなせるということです。この意味にさえ気づけば上記のコードの「ここに挿入」とコメントした位置にこんな処理を追加すればそれっぽい線分(※)がプロットできると思います。
51
51
  ```C

3

追記

2018/09/30 17:33

投稿

KSwordOfHaste
KSwordOfHaste

スコア18404

answer CHANGED
@@ -65,4 +65,7 @@
65
65
 
66
66
  ![イメージ説明](e2731b4bc223c585e8ae09b606971e06.png)
67
67
  ---
68
- ※: 「それっぽい」なんてアバウトな言い方をしましたがそれは「厳密に検証してないのでひょっとしたら本来の線分が通過する画素をプロットしそこねる場合もあるかも知れない」と思ったからです。すみませんが少々面倒だったので検証を省いちゃいました。不備があったらすみません。一つのアイデアとしてみていただければと思います。
68
+ ※: 「それっぽい」なんてアバウトな言い方をしましたがそれは「厳密に検証してないのでひょっとしたら本来の線分が通過する画素をプロットしそこねる場合もあるかも知れない」と思ったからです。すみませんが少々面倒だったので検証を省いちゃいました。不備があったらすみません。一つのアイデアとしてみていただければと思います。
69
+
70
+ ==>追記:傾きを変えて複数の線分の描画を観察してみたところ、案の定、要件を満たさないかも知れないケース(実行例の図の左から2番目の線分)があることに気づきました。
71
+ これが許容できるならよいのですが、まずいならもっと境界条件等を慎重に検討する必要がありそうです。修正方法がわかったら回答へ反映したいと思いますが・・・思いつかないかも知れません。その時はゴメンナサイ

2

実行例が簡単すぎるので複数の線分をプロットした例にする

2018/09/30 17:21

投稿

KSwordOfHaste
KSwordOfHaste

スコア18404

answer CHANGED
@@ -63,7 +63,6 @@
63
63
  ```
64
64
  試しにやってみたところこんな感じになりました。
65
65
 
66
- ![イメージ説明](b688f48ec2222a5f463ba57616309f83.png)
66
+ ![イメージ説明](e2731b4bc223c585e8ae09b606971e06.png)
67
-
68
67
  ---
69
68
  ※: 「それっぽい」なんてアバウトな言い方をしましたがそれは「厳密に検証してないのでひょっとしたら本来の線分が通過する画素をプロットしそこねる場合もあるかも知れない」と思ったからです。すみませんが少々面倒だったので検証を省いちゃいました。不備があったらすみません。一つのアイデアとしてみていただければと思います。

1

不正確な記述を変更

2018/09/30 16:55

投稿

KSwordOfHaste
KSwordOfHaste

スコア18404

answer CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > 基礎的なレンダリングなので、オーソドックスなアルゴリズムがある
4
4
 
5
- とのことですが「基礎的なレンダリング」であるとは必ずしも言えない気がします。お望みの線分は方向によって見た目の線の太さが変わってしまいます。特徴として
5
+ とのことですが「基礎的なレンダリング」であるとは必ずしも言えない気がします。お望みの線分は~~方向によって見た目の線の太さが変わってしまいます~~多くの場合より太い線分が描画されてしまいます。特徴として
6
6
 
7
7
  (A) 本来の線分が通過する画素は必ずプロットする
8
8
  (B) 線分の太さをなるべく細くする