计算机图形学中直线连接算法的Javascript实现

之前在想如何使用Javascript实现时钟的时候,被一个问题难到了:如何在像素级别绘制平滑的直线。

在网上查了一下,后来在图书馆里的一本关于计算机图形学的老书里发现了解决方案。针对这个问题,书上提供了三个算法,分别是简单DDA,对称DDA,Bresenham算法。

下面的是我使用简单DDA和Bresenham算法在浏览器上绘制Hello world的代码。

这里的Hello world 分别是定义了字母的一些”节点“,然后使用连线算法绘制出来的。

代码:

  1. //构造画布,使用DOM动态生成表格
  2. var_container=document.getElementById("container");
  3. varpixs=newArray();
  4. varcanvasTbody=document.createElement("tbody");
  5. varbgColor="black";
  6. varfontColor="green";
  7. varpix_size="4px";
  8. varpix_numbs=81;
  9. vartemp_tr;
  10. vartemp_td;
  11. vartemp_pixrow;
  12. for(vari=pix_numbs;i>=0;i--){
  13. temp_tr=document.createElement("tr");
  14. temp_tr.style.height=pix_size;
  15. temp_pixrow=newArray();
  16. for(varj=0;j<=pix_numbs;j++){
  17. temp_td=document.createElement("td");
  18. temp_td.style.width=pix_size;
  19. temp_td.style.backgroundColor=bgColor;
  20. temp_tr.appendChild(temp_td);
  21. temp_pixrow[j]=temp_td;
  22. }
  23. canvasTbody.appendChild(temp_tr);
  24. pixs[i]=temp_pixrow;
  25. }
  26. varcanvasTable=document.createElement("table");
  27. canvasTable.style.backgroundColor="black";
  28. canvasTable.setAttribute("cellspacing","0");
  29. canvasTable.setAttribute("cellpadding","0");
  30. canvasTable.appendChild(canvasTbody);
  31. _container.appendChild(canvasTable);
  32. //点类,包含坐标信息,有绘制和比较操作
  33. functionpoint(_x,_y){
  34. this.x=_x;
  35. this.y=_y;
  36. }
  37. function_draw(){
  38. if(this.x>pix_numbs||this.y>pix_numbs){
  39. return;
  40. }
  41. pixs[this.y][this.x].style.backgroundColor=fontColor;
  42. }
  43. point.prototype.draw=_draw;
  44. function_equal(_p){
  45. if(!_pinstanceofpoint){
  46. thrownewError();
  47. }
  48. if(this.x==_p.x&&this.y==_p.y){
  49. returntrue;
  50. }else{
  51. returnfalse;
  52. }
  53. }
  54. point.prototype.equal=_equal;
  55. //简单DDA算法构造直线
  56. functionDDA_line(_p1,_p2){
  57. varx1;
  58. vary1;
  59. varx2;
  60. vary2;
  61. var_x;
  62. var_y;
  63. var_p;
  64. vark;
  65. varb;
  66. if(_p1instanceofpoint&&_p2instanceofpoint){
  67. }else{
  68. return;
  69. }
  70. if(_p1.equal(_p2)){
  71. return;
  72. }
  73. if(_p1.x>_p2.x){
  74. x1=_p2.x;
  75. y1=_p2.y;
  76. x2=_p1.x;
  77. y2=_p1.y;
  78. }elseif(_p1.x<_p2.x){
  79. x1=_p1.x;
  80. y1=_p1.y;
  81. x2=_p2.x;
  82. y2=_p2.y;
  83. }elseif(_p1.x==_p2.x){
  84. if(_p1.y>_p2.y){
  85. x1=_p2.x;
  86. y1=_p2.y;
  87. x2=_p1.x;
  88. y2=_p1.y;
  89. }else{
  90. x1=_p1.x;
  91. y1=_p1.y;
  92. x2=_p2.x;
  93. y2=_p2.y;
  94. }
  95. }
  96. if(x1==x2){
  97. _x=x1;
  98. _y=y1;
  99. for(;_y!=y2;_y++){
  100. _p=newpoint(_x,_y);
  101. _p.draw();
  102. }
  103. }else{
  104. k=(y2-y1)/(x2-x1);
  105. b=y1-(k*x1);
  106. if(Math.abs(k)<=1){
  107. _x=x1;
  108. for(;_x!=x2;_x++){
  109. _y=(k*_x)+b;
  110. _y=Math.round(_y);
  111. _p=newpoint(_x,_y);
  112. _p.draw();
  113. }
  114. }else{
  115. _y=y1;
  116. while(_y!=y2){
  117. _x=(_y-b)/k;
  118. _x=Math.round(_x);
  119. _p=newpoint(_x,_y);
  120. _p.draw();
  121. if(y2>y1){
  122. _y++;
  123. }else{
  124. _y--;
  125. }
  126. }
  127. }
  128. }
  129. }
  130. //Bresenham算法构造直线
  131. functionBresenham_line(_p1,_p2){
  132. varx1;
  133. vary1;
  134. varx2;
  135. vary2;
  136. var_x;
  137. var_y;
  138. var_p;
  139. vark;
  140. vard;
  141. if(_p1instanceofpoint&&_p2instanceofpoint){
  142. }else{
  143. return;
  144. }
  145. if(_p1.equal(_p2)){
  146. return;
  147. }
  148. if(_p1.x>_p2.x){
  149. x1=_p2.x;
  150. y1=_p2.y;
  151. x2=_p1.x;
  152. y2=_p1.y;
  153. }elseif(_p1.x<_p2.x){
  154. x1=_p1.x;
  155. y1=_p1.y;
  156. x2=_p2.x;
  157. y2=_p2.y;
  158. }elseif(_p1.x==_p2.x){
  159. if(_p1.y>_p2.y){
  160. x1=_p2.x;
  161. y1=_p2.y;
  162. x2=_p1.x;
  163. y2=_p1.y;
  164. }else{
  165. x1=_p1.x;
  166. y1=_p1.y;
  167. x2=_p2.x;
  168. y2=_p2.y;
  169. }
  170. }
  171. if(x1==x2){
  172. _x=x1;
  173. _y=y1;
  174. for(;_y!=y2;_y++){
  175. _p=newpoint(_x,_y);
  176. _p.draw();
  177. }
  178. }else{
  179. k=(y2-y1)/(x2-x1);
  180. _x=x1;
  181. _y=y1;
  182. if(k>=0&&k<=1){
  183. d=2*(y2-y1)-(x2-x1);
  184. while(_x!=x2){
  185. if(d>=0){
  186. _y++;
  187. d=d-2*(x2-x1);
  188. }
  189. _p=newpoint(_x,_y);
  190. _p.draw();
  191. _x++;
  192. d=d+2*(y2-y1);
  193. }
  194. }elseif(k>1){
  195. d=2*(x2-x1)-(y2-y1);
  196. while(_y!=y2){
  197. if(d>=0){
  198. _x++;
  199. d=d-2*(y2-y1);
  200. }
  201. _p=newpoint(_x,_y);
  202. _p.draw();
  203. _y++;
  204. d=d+2*(x2-x1);
  205. }
  206. }elseif(k<0&&k>=-1){
  207. d=2*(y2-y1)+(x2-x1);
  208. while(_x!=x2){
  209. if(d<=0){
  210. _y--;
  211. d=d+2*(x2-x1);
  212. }
  213. _p=newpoint(_x,_y);
  214. _p.draw();
  215. _x++;
  216. d=d+2*(y2-y1);
  217. }
  218. }elseif(k<-1){
  219. d=2*(x2-x1)+(y2-y1);
  220. while(_y!=y2){
  221. if(d>=0){
  222. _x++;
  223. d=d-2*(y1-y2);
  224. }
  225. _p=newpoint(_x,_y);
  226. _p.draw();
  227. _y--;
  228. d=d+2*(x2-x1);
  229. }
  230. }
  231. }
  232. }
  233. //绘制X
  234. varx1=newpoint(5,60);
  235. x1.draw();
  236. varx2=newpoint(77,60);
  237. x2.draw();
  238. varx3=newpoint(5,25);
  239. x3.draw();
  240. varx4=newpoint(77,25);
  241. x4.draw();
  242. Bresenham_line(x1,x4);
  243. Bresenham_line(x2,x3);
  244. //绘制HELLOWORLD
  245. varp1=newpoint(5,20);
  246. p1.draw();
  247. varp2=newpoint(5,15);
  248. p2.draw();
  249. varp3=newpoint(5,10);
  250. p3.draw();
  251. varp4=newpoint(10,20);
  252. p4.draw();
  253. varp5=newpoint(10,15);
  254. p5.draw();
  255. varp6=newpoint(10,10);
  256. p6.draw();
  257. DDA_line(p1,p3);
  258. DDA_line(p2,p5);
  259. DDA_line(p4,p6);
  260. p1=newpoint(12,20);
  261. p1.draw();
  262. p2=newpoint(12,15);
  263. p2.draw();
  264. p3=newpoint(12,10);
  265. p3.draw();
  266. p4=newpoint(17,20);
  267. p4.draw();
  268. p5=newpoint(17,15);
  269. p5.draw();
  270. p6=newpoint(17,10);
  271. p6.draw();
  272. DDA_line(p1,p3);
  273. DDA_line(p1,p4);
  274. DDA_line(p2,p5);
  275. DDA_line(p3,p6);
  276. p1=newpoint(19,20);
  277. p1.draw();
  278. p2=newpoint(19,10);
  279. p2.draw();
  280. p3=newpoint(24,10);
  281. p3.draw();
  282. DDA_line(p1,p2);
  283. DDA_line(p2,p3);
  284. p1=newpoint(26,20);
  285. p1.draw();
  286. p2=newpoint(26,10);
  287. p2.draw();
  288. p3=newpoint(31,10);
  289. p3.draw();
  290. DDA_line(p1,p2);
  291. DDA_line(p2,p3);
  292. p1=newpoint(33,20);
  293. p1.draw();
  294. p2=newpoint(33,10);
  295. p2.draw();
  296. p3=newpoint(38,20);
  297. p3.draw();
  298. p4=newpoint(38,10);
  299. p4.draw();
  300. DDA_line(p1,p2);
  301. DDA_line(p3,p4);
  302. DDA_line(p1,p3);
  303. DDA_line(p2,p4);
  304. p1=newpoint(45,20);
  305. p1.draw();
  306. p2=newpoint(45,10);
  307. p2.draw();
  308. p3=newpoint(47,15);
  309. p3.draw();
  310. p4=newpoint(49,10);
  311. p4.draw();
  312. p5=newpoint(49,20);
  313. p5.draw();
  314. DDA_line(p1,p2);
  315. DDA_line(p2,p3);
  316. DDA_line(p3,p4);
  317. DDA_line(p4,p5);
  318. p1=newpoint(51,20);
  319. p1.draw();
  320. p2=newpoint(51,10);
  321. p2.draw();
  322. p3=newpoint(56,20);
  323. p3.draw();
  324. p4=newpoint(56,10);
  325. p4.draw();
  326. DDA_line(p1,p2);
  327. DDA_line(p3,p4);
  328. DDA_line(p1,p3);
  329. DDA_line(p2,p4);
  330. p1=newpoint(58,20);
  331. p1.draw();
  332. p2=newpoint(58,16);
  333. p2.draw();
  334. p3=newpoint(58,10);
  335. p3.draw();
  336. p4=newpoint(63,20);
  337. p4.draw();
  338. p5=newpoint(63,16);
  339. p5.draw();
  340. p6=newpoint(63,10);
  341. p6.draw();
  342. DDA_line(p1,p3);
  343. DDA_line(p1,p4);
  344. DDA_line(p4,p5);
  345. DDA_line(p2,p5);
  346. DDA_line(p2,p6);
  347. p1=newpoint(65,20);
  348. p1.draw();
  349. p2=newpoint(65,10);
  350. p2.draw();
  351. p3=newpoint(70,10);
  352. p3.draw();
  353. DDA_line(p1,p2);
  354. DDA_line(p2,p3);
  355. p1=newpoint(72,20);
  356. p1.draw();
  357. p2=newpoint(72,10);
  358. p2.draw();
  359. p3=newpoint(77,20);
  360. p3.draw();
  361. p4=newpoint(77,14);
  362. p4.draw();
  363. DDA_line(p1,p2);
  364. DDA_line(p3,p4);
  365. DDA_line(p1,p3);
  366. DDA_line(p2,p4);

使用方法是在网页中建一个id为”container“的容器,可以是”div“标签

然后把Javascript文件链接进来。即可。

说明:在IE中测试时,有点丑陋。是因为我不知道在IE中使用Javascript动态生成的tbody标签中的单元格之间的间距如何控制。

其他浏览器均可以正常显示。

你可能感兴趣的:(JavaScript)