Bresenham提出的直线生成算法的基本原理是,每次在最大位移方向上走一步,而另一个方向是走步还是不走步取决于误差项的判别,具体的实现过程大家可以去问度娘。我主要是利用canvas画布技术实现了这个过程,算法可能还是有点小问题,欢迎大家给我留言建议,一定虚心接受。

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>中点Bresenham算法</title>
  6. <style>
  7. * {
  8. margin: 0;
  9. padding: 0;
  10. }
  11. body {
  12. font-family: "Helvetica Neue", Helvetica, Arial, "Microsoft Yahei UI", "Microsoft YaHei", SimHei, "\5B8B\4F53", simsun, sans-serif;
  13. color: #555;
  14. }
  15. .left {
  16. float: left;
  17. margin: 20px 0 0 calc((100% - 401px - 602px)/2);
  18. width: 400px;
  19. height: 600px;
  20. border: 1px solid #cccccc;
  21. border-right: none;
  22. }
  23. .left header {
  24. margin: 0 10px;
  25. -webkit-box-sizing: border-box;
  26. -moz-box-sizing: border-box;
  27. box-sizing: border-box;
  28. height: 60px;
  29. line-height: 60px;
  30. font-size: 18px;
  31. /*text-align: center;*/
  32. border-bottom: 2px solid #aaa;
  33. }
  34. .start {
  35. margin: 0 25px;
  36. line-height: 80px;
  37. /*text-align: center;*/
  38. }
  39. .left input[type="text"] {
  40. padding: 2px 5px;
  41. width: 30px;
  42. -webkit-box-sizing: border-box;
  43. -moz-box-sizing: border-box;
  44. box-sizing: border-box;
  45. background-color: #f5f5f5;
  46. border: 1px solid #cccccc;
  47. }
  48. button {
  49. border: none;
  50. display: inline-block;
  51. outline: 0;
  52. padding: 6px 16px;
  53. margin-bottom: 10px;
  54. vertical-align: middle;
  55. overflow: hidden;
  56. text-decoration: none;
  57. color: #fff;
  58. background-color: #F88E8B;
  59. text-align: center;
  60. transition: .2s ease-out;
  61. cursor: pointer;
  62. white-space: nowrap;
  63. box-shadow: 0px 1px 3px rgba(0,0,0,0.12), 0px 1px 2px rgba(0,0,0,0.24);
  64. }
  65. button:hover {
  66. background-color: #F35F5C;
  67. }
  68. #stroke {
  69. margin-left: 25px;
  70. }
  71. #reset {
  72. margin-left: 10px;
  73. }
  74. /*.left button {
  75. display: block;
  76. margin: 0 auto;
  77. }*/
  78. #xy {
  79. /*display: none;*/
  80. }
  81. .left p {
  82. line-height: 40px;
  83. text-align: center;
  84. }
  85. .table {
  86. position: relative;
  87. padding-top: 30px;
  88. max-height: 373px;
  89. overflow-y: auto;
  90. -webkit-box-sizing: border-box;
  91. -moz-box-sizing: border-box;
  92. box-sizing: border-box;
  93. }
  94. #thead {
  95. position: absolute;
  96. z-index: 999;
  97. width: 370px;
  98. margin-left: 10px;
  99. }
  100. .left table {
  101. margin: 0 0 10px 10px;
  102. width: 370px;
  103. border-collapse:collapse;
  104. }
  105. .left table th{
  106. width: 33.3333%;
  107. height: 30px;
  108. border: 1px solid #cccccc;
  109. background-color: #f1f1f1;
  110. }
  111. .left table td{
  112. width: 33.3333%;
  113. height: 30px;
  114. text-align: center;
  115. border: 1px solid #cccccc;
  116. }
  117. #myCanvas {
  118. display: block;
  119. float: left;
  120. margin-top: 20px;
  121. background-color: #fffdf6;
  122. border: 1px solid #cccccc;
  123. }
  124. </style>
  125. </head>
  126. <body>
  127. <div class="left" id="left">
  128. <header>&nbsp;&nbsp;中点 <strong>Bresenham</strong> 算法</header>
  129. <div class="start">
  130. 直线方程 :
  131. <input type="text" id="A" required autocomplete="off"> x + <input type="text" id="B" required autocomplete="off"> y + <input type="text" id="C" required autocomplete="off"> = 0
  132. </div>
  133. <button id="stroke">开始绘制</button>
  134. <button id="reset">重置</button>
  135. <div id="xy" style="display: none;">
  136. <p><strong>坐标值</strong></p>
  137. <table id="thead">
  138. <tr>
  139. <th> X </th>
  140. <th> Y </th>
  141. <th> d </th>
  142. </tr>
  143. </table>
  144. <div class="table">
  145. <table id="table">
  146. <!-- <tr>
  147. <th> X </th>
  148. <th> Y </th>
  149. <th> d </th>
  150. </tr> -->
  151. </table>
  152. </div>
  153. </div>
  154. </div>
  155. <canvas id="myCanvas" width="600" height="600">
  156. 您的浏览器不支持canvas,请升级浏览器!
  157. </canvas>
  158. <script>
  159. //*-----------------canvas画坐标表格---------------------*
  160. var canvas=document.getElementById("myCanvas");
  161. var context=canvas.getContext("2d");
  162. function drowAxes() {
  163. // 描绘边框
  164. var grid_cols = 20;
  165. var grid_rows = 20;
  166. var cell_height = canvas.height / grid_rows;
  167. var cell_width = canvas.width / grid_cols;
  168. context.lineWidth = 1;
  169. context.strokeStyle = "#cccccc";
  170. // 结束边框描绘
  171. context.beginPath();
  172. // 准备画横线
  173. for (var col = 1; col <= grid_cols; col++) {
  174. var x = col * cell_width;
  175. if(col == 10) {
  176. context.beginPath();
  177. context.strokeStyle = "#2FB9D6";
  178. context.moveTo(x+0.5,0);
  179. context.lineTo(x+0.5,canvas.height);
  180. context.stroke();
  181. }
  182. else {
  183. context.beginPath();
  184. context.strokeStyle = "#cccccc";
  185. context.moveTo(x+0.5,0);
  186. context.lineTo(x+0.5,canvas.height);
  187. context.stroke();
  188. }
  189. }
  190. //准备画竖线
  191. for(var row = 1; row <= grid_rows; row++){
  192. var y = row * cell_height;
  193. if(row == 10) {
  194. context.beginPath();
  195. context.strokeStyle = "#2FB9D6";
  196. context.moveTo(0,y+0.5);
  197. context.lineTo(canvas.width, y+0.5);
  198. context.stroke();
  199. }
  200. else {
  201. context.beginPath();
  202. context.strokeStyle = "#cccccc";
  203. context.moveTo(0,y+0.5);
  204. context.lineTo(canvas.width, y+0.5);
  205. context.stroke();
  206. }
  207. }
  208. context.stroke();
  209. //给坐标轴加刻度
  210. for(var i=0;i <= grid_cols;i++) {
  211. var x = i * cell_width;
  212. context.font="13px Arial";
  213. context.fillStyle="#000";
  214. context.fillText(-10+i,5 + x,315);
  215. }
  216. for(var i=0;i <= grid_rows;i++) {
  217. var y = i * cell_height;
  218. context.font="13px Arial";
  219. context.fillStyle="#000";
  220. context.fillText(10-i,305,15 + y);
  221. }
  222. }
  223. //坐标生成及Canvas画点函数
  224. function drawDot(x,y,d) {
  225. var tr=document.createElement("tr");
  226. var td1=document.createElement("td");
  227. var node1=document.createTextNode(" "+Math.round(x)+" ");
  228. td1.appendChild(node1);
  229. tr.appendChild(td1);
  230. var td2=document.createElement("td");
  231. var node2=document.createTextNode(" "+Math.round(y)+" ");
  232. td2.appendChild(node2);
  233. tr.appendChild(td2);
  234. var td3=document.createElement("td");
  235. var node3=document.createTextNode(" "+d.toFixed(2)+" ");
  236. td3.appendChild(node3);
  237. tr.appendChild(td3);
  238. document.getElementById("table").appendChild(tr);
  239. //坐标处理
  240. var X,Y;
  241. X= Math.round(x)*30;
  242. Y=- Math.round(y)*30;
  243. //表格中绘制坐标点
  244. context.fillStyle="#2FB9D6";
  245. context.beginPath();
  246. context.arc(X,Y,4,0,Math.PI*2,true);
  247. context.closePath();
  248. context.fill();
  249. }
  250. //判断输入的字符是否为整数
  251. function IsInteger()
  252. {
  253. var str1 = document.getElementById('A').value.trim();
  254. var str2 = document.getElementById('B').value.trim();
  255. var str3 = document.getElementById('C').value.trim();
  256. if(str1.length!=0 && str2.length!=0 && str3.length!=0){
  257. reg=/^[-+]?\d*$/;
  258. if(!reg.test(str1) || !reg.test(str2) || !reg.test(str3)){
  259. alert("对不起,请输入整数!");//请将“整数类型”要换成你要验证的那个属性名称!
  260. return false;
  261. }
  262. else {return true;}
  263. }
  264. }
  265. window.onload = drowAxes();
  266. var canvas_flag=0;//设置是否画线的标记变量
  267. //*-----------------中点Bresenham算法求坐标--------------------*
  268. document.getElementById("stroke").onclick=function Bresenham(){
  269. var xy=document.getElementById("xy");
  270. var A=document.getElementById("A").value;
  271. var B=document.getElementById("B").value;
  272. var C=document.getElementById("C").value;
  273. if(A.length == 0 || B.length == 0 || C.length == 0) {alert("请填写直线方程的系数!")}
  274. //直线上取两个点
  275. if(xy.style.display === 'none' && A.length != 0 && B.length != 0 && C.length != 0 && IsInteger()) {
  276. if(A==0 && B==0 && C!=0) {alert("输入错误,请重新输入!");}
  277. else if(A==0 && B==0 && C==0) {alert("输入数据不能全部为0!")}
  278. else if(A==0 && B!=0) { //y=c 类方程
  279. context.translate(300,300);//将坐标原点移到(300,300)处
  280. //绘制直线
  281. var c=-Math.round(C/B)*30;
  282. context.beginPath();
  283. context.strokeStyle="#2FB9D6";
  284. context.moveTo(-300,c);
  285. context.lineTo(300,c);
  286. context.closePath();
  287. context.stroke();
  288. canvas_flag=1;//标记变量置1
  289. }
  290. else if(A!=0 && B==0) { //x=c 类方程
  291. context.translate(300,300);//将坐标原点移到(300,300)处
  292. //绘制直线
  293. var c=-Math.round(C/A)*30;
  294. context.beginPath();
  295. context.strokeStyle="#2FB9D6";
  296. context.moveTo(c,-300);
  297. context.lineTo(c,300);
  298. context.closePath();
  299. context.stroke();
  300. canvas_flag=1;//标记变量置1
  301. }
  302. else if(-A/B>=0){ //斜率大于等于0的情况
  303. xy.style.display = 'block';
  304. var x0,y0,x1,y1;
  305. var vx,vy;
  306. var d; //增长量
  307. var m,n; //循环变量
  308. var x,y;
  309. var k = -A/B;
  310. if(k>=0 && k<=1) { //k大于等于0小于等于1的情况
  311. x0 = -5;x1 = 5;
  312. y0 = (-C -A*x0)/B;
  313. y1 = (-C -A*x1)/B;
  314. vx = x1 - x0,vy = y1 - y0;
  315. x = x0,y = y0;
  316. n = x0;
  317. m = x1;
  318. d = vx - 2*vy; //初始化d
  319. }
  320. else if(k>1) { //k大于1的情况
  321. y0 = -5;y1 = 5;
  322. x0 = (-C -B*y0)/A;
  323. x1 = (-C -B*y1)/A;
  324. vx = x1 - x0,vy = y1 - y0;
  325. x = x0,y = y0;
  326. n = y0;
  327. m = y1;
  328. d = 2*vx - vy; //初始化d
  329. }
  330. context.translate(300,300);//将坐标原点移到(300,300)处
  331. for(var i=n;i<=m;i++) {
  332. //----------------算法核心代码---------------
  333. if(k>=0 && k<=1) { //k大于等于0小于等于1的情况
  334. drawDot(x,y,d);
  335. if(d<0) {
  336. x = x + 1;
  337. y = y + 1;
  338. d = d + 2*vx - 2*vy;
  339. }
  340. else {
  341. x = x + 1;
  342. y = y;
  343. d = d - 2*vy;
  344. }
  345. }
  346. else if(k>1) { //k大于1的情况
  347. drawDot(x,y,d);
  348. if(d<0) {
  349. x = x;
  350. y = y + 1;
  351. d = d + 2*vx;
  352. }
  353. else {
  354. x = x + 1;
  355. y = y + 1;
  356. d = d - 2*vy + 2*vx;
  357. }
  358. }
  359. }
  360. //绘制直线
  361. var X0,Y0,X1,Y1;
  362. X0= Math.round(x0)*30;
  363. Y0=-Math.round(y0)*30;
  364. X1=Math.round(x1)*30;
  365. Y1=-Math.round(y1)*30;
  366. context.beginPath();
  367. context.strokeStyle="#2FB9D6";
  368. context.moveTo(X0,Y0);
  369. context.lineTo(X1,Y1);
  370. context.closePath();
  371. context.stroke();
  372. canvas_flag=1;//标记变量置1
  373. }
  374. else if(-A/B<0){ //斜率小于0的情况
  375. //将直线转化为斜率大于等于0的情况,然后求关于x轴对称的直线就行
  376. xy.style.display = 'block';
  377. A = -A;
  378. var x0,y0,x1,y1;
  379. var vx,vy;
  380. var d; //增长量
  381. var m,n; //循环变量
  382. var x,y;
  383. var k = -A/B;
  384. if(k>=0 && k<=1) { //k大于等于0小于等于1的情况
  385. x0 = -5;x1 = 5;
  386. y0 = (-C -A*x0)/B;
  387. y1 = (-C -A*x1)/B;
  388. vx = x1 - x0,vy = y1 - y0;
  389. x = x0,y = y0;
  390. n = x0;
  391. m = x1;
  392. d = vx - 2*vy; //初始化d
  393. }
  394. else if(k>1) { //k大于1的情况
  395. y0 = -5;y1 = 5;
  396. x0 = (-C -B*y0)/A;
  397. x1 = (-C -B*y1)/A;
  398. vx = x1 - x0,vy = y1 - y0;
  399. x = x0,y = y0;
  400. n = y0;
  401. m = y1;
  402. d = 2*vx - vy; //初始化d
  403. }
  404. context.translate(300,300);//将坐标原点移到(300,300)处
  405. for(var i=n;i<=m;i++) {
  406. //----------------算法核心代码---------------
  407. if(k>=0 && k<=1) { //k大于等于0小于等于1的情况
  408. drawDot(-x,y,d);
  409. if(d<0) {
  410. x = x + 1;
  411. y = y + 1;
  412. d = d + 2*vx - 2*vy;
  413. }
  414. else {
  415. x = x + 1;
  416. y = y;
  417. d = d - 2*vy;
  418. }
  419. }
  420. else if(k>1) { //k大于1的情况
  421. drawDot(-x,y,d);
  422. if(d<0) {
  423. x = x;
  424. y = y + 1;
  425. d = d + 2*vx;
  426. }
  427. else {
  428. x = x + 1;
  429. y = y + 1;
  430. d = d - 2*vy + 2*vx;
  431. }
  432. }
  433. }
  434. //绘制直线
  435. var X0,Y0,X1,Y1;
  436. X0= Math.round(-x0)*30;
  437. Y0=-Math.round(y0)*30;
  438. X1=Math.round(-x1)*30;
  439. Y1=-Math.round(y1)*30;
  440. context.beginPath();
  441. context.strokeStyle="#2FB9D6";
  442. context.moveTo(X0,Y0);
  443. context.lineTo(X1,Y1);
  444. context.closePath();
  445. context.stroke();
  446. canvas_flag=1;//标记变量置1
  447. }
  448. }
  449. };
  450. //重新绘制
  451. document.getElementById("reset").onclick=function reset(){
  452. var A=document.getElementById("A").value;
  453. var B=document.getElementById("B").value;
  454. var C=document.getElementById("C").value;
  455. if(A.length == 0 && B.length == 0 && C.length == 0) {alert("没有输入数据!")}
  456. else {
  457. //清空input输入框
  458. document.getElementById("A").value="";
  459. document.getElementById("B").value="";
  460. document.getElementById("C").value="";
  461. }
  462. if(canvas_flag==1) {
  463. context.clearRect(-300,-300,600,600); //清空画布
  464. context.translate(-300,-300); //将坐标原点还原
  465. drowAxes(); //重绘坐标轴
  466. canvas_flag=0;
  467. }
  468. if(document.getElementById("xy").style.display === 'block') {
  469. document.getElementById("xy").style.display = 'none';
  470. var table = document.getElementById("table");
  471. while(table.hasChildNodes()) //当table下还存在子节点时 循环继续
  472. {
  473. table.removeChild(table.firstChild);
  474. }
  475. }
  476. };
  477. </script>
  478. </body>
  479. </html>

利用canvas实现的中点Bresenham算法的更多相关文章

  1. 《图形学》实验七:中点Bresenham算法画椭圆

    开发环境: VC++6.0,OpenGL 实验内容: 使用中点Bresenham算法画椭圆. 实验结果: 代码: #include <gl/glut.h> #define WIDTH 50 ...

  2. 《图形学》实验六:中点Bresenham算法画圆

    开发环境: VC++6.0,OpenGL 实验内容: 使用中点Bresenham算法画圆. 实验结果: 代码: #include <gl/glut.h> #define WIDTH 500 ...

  3. 《图形学》实验四:中点Bresenham算法画直线

    开发环境: VC++6.0,OpenGL 实验内容: 使用中点Bresenham算法画直线. 实验结果: 代码: //中点Bresenham算法生成直线 #include <gl/glut.h& ...

  4. Python使用DDA算法和中点Bresenham算法画直线

    title: "Python使用DDA算法和中点Bresenham算法画直线" date: 2018-06-11T19:28:02+08:00 tags: ["图形学&q ...

  5. [DEBUG]椭圆的中点Bresenham算法边缘绘制出现错误

    在使用椭圆的中点Bresenham算法绘制椭圆时, 当椭圆足够大时, 椭圆的边缘会出现下面这种情况. 出错原因: 将a, b声明为了int类型, 导致中点判别式中发生溢出 关注后面的a*b*a*b当a ...

  6. 《图形学》实验五:改进的Bresenham算法画直线

    开发环境: VC++6.0,OpenGL 实验内容: 使用改进的Bresenham算法画直线. 实验结果: 代码: //中点Bresenham算法生成直线 #include <gl/glut.h ...

  7. 直线的中点Bresenham算法的实现

    一.实验目的 1.掌握在MFC中搭建图形绘制的基本框架的方法: 2.将直线的中点Bresenham算法转化成可执行代码. 二.实验内容 1. 通过分析具体数据在中点Bresenham算法上的执行过程, ...

  8. Bresenham算法画填充圆及SDL代码实现

    画圆是计算机图形操作中一个非常重要的需求.普通的画圆算法需要大量的浮点数参与运算,而众所周知,浮点数的运算速度远低于整形数.而最终屏幕上影射的像素的坐标均为整形,不可能是连续的线,所以浮点数运算其实纯 ...

  9. 基于Bresenham算法画圆

    bresenham算法画圆思想与上篇 bresenham算法画线段 思想是一致的 画圆x^2+y^2=R^2 将他分为8个部分,如上图 1. 只要画出1中1/8圆的圆周,剩下的就可以通过对称关系画出这 ...

随机推荐

  1. 【jmeter】参数化User Defined Variables与User Parameters

    偶然发现JMeter中有两个元件(User Defined Variables与User Parameters)很相近,刚开始时我也没注意,两者有什么不同.使用时却发现两者使用场景有些不同,现在小结一 ...

  2. JavaScript中的继承模式总结

    一.总结: //js中的几种继承 //原型链的问题,包含引用类型的原型属性会被实例共享,子类型无法给超类型传递参数 function SuperType() { this.colors = [&quo ...

  3. C基础--关于typedef的用法总结

    转自:http://blog.csdn.net/wangqiulin123456/article/details/8284939 在C还是C++代码中,typedef都使用的很多,在C代码中尤其是多. ...

  4. Cpk

    CPK:Complex Process Capability index 的缩写,是现代企业用于表示制程能力的指标.制程能力是过程性能的允许最大变化范围与过程的正常偏差的比值.制程能力研究在於确认这些 ...

  5. 不用配置tnsnames.ora,直接通过PL/SQL访问远程数据库

  6. PLSQL_性能优化工具系列09_SQL Plan Management

    2014-09-24 Created By BaoXinjian

  7. cf519D . A and B and Interesting Substrings 数据结构map

    题意: 已知26个小写字母有各自的权值(正,负,或0) 现在给出一个字符串,长度<=1e5 问这个字符串有多少个子串满足: 开头的字母和结尾的字母一样 字符串除了开头和结尾的字母外,其余的字母的 ...

  8. Yii 框架表单验证---实例

  9. memcached完全剖析–1. memcached的基础

    系列文章导航: memcached完全剖析–1. memcached的基础 memcached全面剖析–2. 理解memcached的内存存储 memcached全面剖析–3. memcached的删 ...

  10. border-radius 样式表CSS3圆角属性

    border-radius 是CSS3圆角属性,用来实现DIV层的4个边框画成圆角. 一.语法: border-radius : none | <length>{1,4} [/ <l ...