[Canvas绘图] 第14节 “路”在何方
来源:互联网 发布:手机淘宝5.10.3旧版本 编辑:程序博客网 时间:2024/06/16 06:41
本节目标:
(1) 对数据映射点阵进行线条勾勒处理
代码就是这么多,接下来就是验证成果的时候了,上图:
(1) 对数据映射点阵进行线条勾勒处理
实现步骤:
我在尝试有没有更好的处理方法勾勒出轮廓线条,于是想到了递归,如果根据原始映射图的点的关系,或许可以让程序自己找出合适的路径,但试了才发现递归的运算量相当巨大,完全会被卡死。所以最终形成了简化版,代码如下:
/*** @usage 获取轮廓* @author mw* @date 2015年12月06日 星期日 07:50:37 * @param* @return**/function getSketch() {plot.init();setPreference();setSector(4,1,1,1);//axis(0, 0, 180);//数据录入var map = new Map();for (var i = 0; i < $picDataArray.length; i++) {map.put($picDataArray[i][0], $picDataArray[i][1]);}map.sort();//存放经过排序的map的每个x坐标对应的y坐标的数量var lenArray = new Array();var len = 0;//数据打印校验var s = "********";for (var i = 0; i < map.size(); i++) {x = map.keys[i];len = map.get(x).length;lenArray.push(len);s += "<x =" + x + ", len = "+len+"> ";}var pointInfo = map.print() + s;var pointInfoNode = document.createTextNode(pointInfo);document.body.appendChild(pointInfoNode);//确保lenArray已经取得//然后继续//点图for (var i = 0; i < map.size(); i++) {x = map.keys[i];//每个x对应的y序列for (j = 0; j < lenArray[i]; j++) {y = map.get(x)[j];fillCircle(x, y, 1);}}plot.translate(-200, 150);var path = new Path();path.setMap(map);path.search();//window.alert(pointInMap(41, 72, path.map));var pathArr = new Array();pathArr = path.pathArray;var pointInfo2 = "**************" + pathArr.length + "********";for (var i = 0; i < pathArr.length; i++) {pointInfo2 += "[" + pathArr[i] + "], ";}var pointInfoNode2 = document.createTextNode(pointInfo2);document.body.appendChild(pointInfoNode2);for (var i=0; i < pathArr.length-1; i++) {plot.moveTo(pathArr[i][0] * 1.2, pathArr[i][1]*1.2).lineTo(pathArr[i][2] * 1.2, pathArr[i][3]*1.2);}plot.stroke();}
这里需要判断点是否在映射图里面,开始时我选择让点完全相等才判true,但这样导致本来就稀疏的线条更加稀疏,后来我想了想,觉得只情愿让点和线多出来。于是采用了范围判定。如下:
/*** @usage 判断坐标点是否在map中* @author mw* @date 2015年12月06日 星期日 07:50:37 * @param 点(x, y), 映射集合map* @return true 或 false**/function pointInMap(x, y, map, range) {//传入的映射集map一般是经过排序的,并且去除了重复元素。var pmap = new Map();pmap = map;range = range ? range : 5;for (var i = 0; i <pmap.size() ; i++) {if (x == pmap.keys[i]) {var len = pmap.get(x).length;for (var j = 0; j < len; j++) {if (Math.abs(y - pmap.get(x)[j]) <= range) {return true;}}}}return false;}
接下来是递归算法,本来应该是全方位搜索,结果只能实现四方向搜索,如下:
/*** @usage 路径搜寻* @author mw* @date 2015年12月06日 星期日 08:01:32 * @param 以(x, y)点为起点, 在map中进行递归的路径搜寻。* 搜寻条件是(x1, y1)必须满足x1<-[x, x+1], y1<-[y-1, y+1]并且在map中* @return **///Path类function Path() {this.map = new Map();//存放已经处理过的点this.dealed = new Map();this.pathArray = new Array();//附带找出图形中心this.xCenter = 0;this.yCenter = 0;this.yMax = -10000;this.yMin = 10000;//递归深度,代表连续线段的长度this.level = 10;this.LEVEL = 10;//路径上的控制点this.xCur = 0;this.ycur = 0;this.xOri = 0;this.yOri = 0;this.setMap = function(map) {this.map = map;this.pathArray.length = 0;}this.pathSearch = function(x, y, direct) {//路径向左向下延伸,刚好是一半的圆周方向switch (direct) {case 1:if (pointInMap(x+1, y-1, this.map)) {this.level--;this.xCur = x + 1;this.yCur = y-1;this.pathSearch(x+1, y-1, 1);//}break;case 2:if (pointInMap(x+1, y, this.map)) {this.level--;this.xCur = x + 1;this.yCur = y;this.pathSearch(x+1, y, 2); //}break;case 3:if (pointInMap(x+1, y+1, this.map)) {this.level--;this.xCur = x + 1;this.yCur = y+1;this.pathSearch(x+1, y+1, 3);}break;case 4:if (pointInMap(x, y+1, this.map)) {this.level--;this.xCur = x ;this.yCur = y-1;this.pathSearch(x, y+1, 4);}break;default: break;}if (this.level < 0) {//此处简单处理,尽量减少处理量,增加处理速度,所以路径不会很全//要是想要全路径需要把dealed升级为map,记录并对比方向量var k = (this.yCur - this.yOri) / (this.xCur - this.xOri) ;var n = Math.abs(this.xCur - this.xOri);for (var i = 0; i < n-1; i++) {this.dealed.put(this.xOri + i, this.yOri + k * i);}//增加处理量的方法//this.dealed.put(this.xOri, this.yOri);this.xOri = this.xOri - this.xCenter;this.yOri = this.yOri - this.yCenter;this.xCur = this.xCur - this.xCenter;this.yCur = this.yCur - this.yCenter;this.pathArray.push([this.xOri-1, this.yOri-1, this.xCur+1, this.yCur+1]);this.level = this.LEVEL;}//最后必然有某点不具有下一个相邻点而结束递归。return true;};this.search = function () {if (!this.dealed.isEmpty()) {this.dealed.empty();}if (0 == this.map.size()) return false;this.map.sort();var x0 = 0;var y0 = 0;var size = this.map.size();var len = 0;this.xCenter = (this.map.keys[0] + this.map.keys[size-1]) / 2;//求y中心点for (var i = 0; i < size; i++) {x0 = this.map.keys[i];len = this.map.get(x0).length;for (var j =0; j < len; j++) {y0 = this.map.get(x0)[j];if (y0 > this.yMax) this.yMax = y0;if (y0 < this.yMin) this.yMin = y0;}}this.yCenter = (this.yMax + this.yMin) / 2;//window.alert(this.xCenter + ", " + this.yCenter);//路径递归的耗时操作,相当耗时for (var i = 0; i < size; i++) {x0 = this.map.keys[i];len = this.map.get(x0).length;for (var j =0; j < len; j++) {y0 = this.map.get(x0)[j];//整个处理过程x从小到大,y从小到大处理,但路径上的点会超前循环,//所以要进行判断来提高效率if (!pointInMap(x0, y0, this.dealed)) {//此处每个点都视作起点,看它们有没有足够长的路径this.level = this.LEVEL;this.xCur = x0;this.yCur = y0;this.xOri = x0;this.yOri = y0;//向四个方向找路径this.pathSearch(x0, y0, 1);this.level = this.LEVEL;this.xCur = x0;this.yCur = y0;this.xOri = x0;this.yOri = y0;this.pathSearch(x0, y0, 2);this.level = this.LEVEL;this.xCur = x0;this.yCur = y0;this.xOri = x0;this.yOri = y0;this.pathSearch(x0, y0, 3);this.level = this.LEVEL;this.xCur = x0;this.yCur = y0;this.xOri = x0;this.yOri = y0;this.pathSearch(x0, y0, 4);}}}window.alert("finished");};}
代码就是这么多,接下来就是验证成果的时候了,上图:
(1) 线条过滤长度10, 范围容许5,需要绘线段713
(2) 线条过滤长度5, 范围容许5,需要绘线段966
(3) 线条过滤长度2, 范围容许5,需要绘线段999
(4) 死算模式,需要绘线段3372
大致也只能得到这种效果了,本节到此结束。
这些图拿去跟朋友说是手绘的,看他们信不信。
0 0
- [Canvas绘图] 第14节 “路”在何方
- [Canvas绘图] 第15节 逐“路”法则
- [Canvas绘图] 第01节 画布准备
- [Canvas绘图] 第03节 “矩”重若轻
- [Canvas绘图] 第04节 多边家族
- [Canvas绘图] 第05节 火柴天堂
- [Canvas绘图] 第06节 车轮滚滚
- [Canvas绘图] 第08节 "8"解九妹
- [Canvas绘图] 第10节 图片加载
- [Canvas绘图] 第11节 四大美人
- [Canvas绘图] 第12节 帅哥降临
- [Canvas绘图] 第13节 线条勾勒
- [Canvas绘图] 第16节 路见不平
- [Canvas绘图] 第26节 生成表格
- [Canvas绘图] 第27节 三维初探
- [Canvas绘图] 第29节 葵花点穴
- [Canvas绘图] 第30节 沙场点兵
- [Canvas绘图] 第31节 连通实验
- 控件进度条
- TCP 流协议和消息分帧的理解
- 哈希表总结
- 欢迎使用CSDN-markdown编辑器
- PAT 1007 素数对猜想
- [Canvas绘图] 第14节 “路”在何方
- 切换jdk,但是运行java -version仍然不变的原因
- HttpServletRequest常用获取URL相关的方法
- 电子或通信领域当前的主流技术及其社会需求调查报告
- forget mysql pw problem
- 详解D3D/OpenGL光栅化(1)
- 【指导】git 日志长度、日志开头、tag 命名的 hook 部署(gerrit ref-update)
- New UI-为TextView设置超链接跳转的三个方法
- ListView 属性详解 参考1