回答編集履歴

2

法線ベクトルの算出アルゴリズムについてのメモを追加

2018/04/12 08:05

投稿

defghi1977
defghi1977

スコア4756

test CHANGED
@@ -135,3 +135,9 @@
135
135
  }
136
136
 
137
137
  ```
138
+
139
+
140
+
141
+ NOTE:
142
+
143
+ 途中で求めた法線ベクトル二つを足して簡易的に2で割っているけれど, 本当はもっと適した算出法があるかもしれない.(この操作が引き起こす実用上の問題は不明)

1

コードを追加

2018/04/12 08:05

投稿

defghi1977
defghi1977

スコア4756

test CHANGED
@@ -7,3 +7,131 @@
7
7
 
8
8
 
9
9
  三点から得られたポリゴン面に垂直に立つ法線ベクトルを求め, それを真上から射影すればその方向と傾きが得られる.
10
+
11
+
12
+
13
+ ---
14
+
15
+ 例えばここを参考としてスクリプトを組んで見る.
16
+
17
+ [http://www.dstorm.co.jp/dsproducts/developers/Technical_Data/CalcNormal.html](http://www.dstorm.co.jp/dsproducts/developers/Technical_Data/CalcNormal.html)
18
+
19
+ ```HTML
20
+
21
+ <canvas id="canvas" width="400" height="400" style="background-color:yellow;"></canvas>
22
+
23
+ ```
24
+
25
+ ```JavaScript
26
+
27
+ "use strict";
28
+
29
+ {
30
+
31
+ function getNormal(a, b){
32
+
33
+ const vec = [
34
+
35
+ a[1] * b[2] - a[2] * b[1],
36
+
37
+ a[2] * b[0] - a[0] * b[2],
38
+
39
+ a[0] * b[1] - a[1] * b[0]
40
+
41
+ ];
42
+
43
+ const norm = Math.sqrt(vec.reduce((prev, val) => prev + val * val, 0));
44
+
45
+ return vec.map((val, i) => vec[i] /= norm);
46
+
47
+ }
48
+
49
+ function plot(table){
50
+
51
+ const ctx = canvas.getContext("2d");
52
+
53
+ ctx.strokeStyle = ctx.fillStyle = "red";
54
+
55
+ ctx.lineWidth = 2;
56
+
57
+ const unit = 100, arrow = 50;
58
+
59
+ const marker = new Path2D("M0,-5L5,0 0 5z");
60
+
61
+ const rows = table.length, cols = table[0].length;
62
+
63
+ for(let y = 0; y < rows-1; y++){
64
+
65
+ for(let x = 0; x < cols-1; x++){
66
+
67
+ ctx.save();
68
+
69
+ //ベクトルの描画基準
70
+
71
+ ctx.translate(unit * (x + 0.5), unit * (y + 0.5));
72
+
73
+ //上半三角
74
+
75
+ const normalT = getNormal(
76
+
77
+ [1, 0, table[y][x+1] - table[y][x]],
78
+
79
+ [0, 1, table[y+1][x] - table[y][x]]
80
+
81
+ );
82
+
83
+ //下半三角
84
+
85
+ const normalB = getNormal(
86
+
87
+ [-1, 0, table[y+1][x] - table[y+1][x+1]],
88
+
89
+ [0, -1, table[y][x+1] - table[y+1][x+1]]
90
+
91
+ );
92
+
93
+ //平均
94
+
95
+ const normal = normalT.map((val, i) => (val + normalB[i])/2)
96
+
97
+ ctx.beginPath();
98
+
99
+ ctx.moveTo(0,0);
100
+
101
+ ctx.lineTo(normal[0] * arrow, normal[1] * arrow);
102
+
103
+ ctx.stroke();
104
+
105
+ //marker
106
+
107
+ ctx.translate(normal[0] * arrow, normal[1] * arrow);
108
+
109
+ ctx.rotate(Math.atan2(normal[1], normal[0]));
110
+
111
+ ctx.fill(marker);
112
+
113
+ ctx.restore();
114
+
115
+ }
116
+
117
+ }
118
+
119
+ }
120
+
121
+ plot([
122
+
123
+ [0, 0, 1, 0, 0],
124
+
125
+ [1, 1, 1, 1, 1],
126
+
127
+ [2, 3, 2, 4, 2],
128
+
129
+ [3, 3, 3, 3, 3],
130
+
131
+ [4, 3, 5, 6, 7]
132
+
133
+ ]);
134
+
135
+ }
136
+
137
+ ```