From dcb40f30870879c24dbcb7efdaf3da6ac28cb8b1 Mon Sep 17 00:00:00 2001 From: kekee000 Date: Tue, 24 Mar 2015 00:51:45 +0800 Subject: [PATCH] modify split params --- demo/js/findBreakPoint.js | 13 +++- demo/js/fitContours.js | 66 +++++++++++----- src/graphics/image/findBreakPoints.js | 106 +++++++++++++++++++++----- src/graphics/image/fitBezier.js | 6 +- src/graphics/image/fitCurve.js | 11 ++- src/graphics/vector.js | 16 +++- 6 files changed, 170 insertions(+), 48 deletions(-) diff --git a/demo/js/findBreakPoint.js b/demo/js/findBreakPoint.js index 1e02658..ab70fb8 100644 --- a/demo/js/findBreakPoint.js +++ b/demo/js/findBreakPoint.js @@ -8,7 +8,7 @@ define( var fitBezier = require('graphics/image/fitBezier'); var findBreakPoints = require('graphics/image/findBreakPoints'); var pathUtil = require('graphics/pathUtil'); - var data = require('demo/../data/image-contours3'); + var data = require('demo/../data/image-contours1'); var drawPath = require('render/util/drawPath'); var entry = { @@ -38,6 +38,10 @@ define( contour = pathUtil.scale(contour, 0.1); }); + breakPoints.forEach(function (p) { + console.log(p.right); + }); + html = ''; for (var i = 0, l = breakPoints.length; i < l; i++) { var c = "break"; @@ -47,8 +51,11 @@ define( else if(breakPoints[i].inflexion) { c = 'inflexion'; } - - html += ''; + var width = ''; + if (breakPoints[i].right == 1) { + width = 'width: 4px;height: 4px'; + } + html += ''; } $('#points-break').html(html); diff --git a/demo/js/fitContours.js b/demo/js/fitContours.js index 57b8052..833715e 100644 --- a/demo/js/fitContours.js +++ b/demo/js/fitContours.js @@ -9,20 +9,29 @@ define( var fitBezier = require('graphics/image/fitBezier'); var findBreakPoints = require('graphics/image/findBreakPoints'); var pathUtil = require('graphics/pathUtil'); - var data = require('demo/../data/image-contours4'); + var vector = require('graphics/vector'); + var data = require('demo/../data/image-contours1'); var drawPath = require('render/util/drawPath'); - - function fitContour(data) { data = pathUtil.scale(data, 10); var breakPoints = findBreakPoints(data); + + breakPoints.forEach(function (p) { + console.log(p.right); + }); + var resultContour = []; + var isLast; + var start; + var end; + var lasttHat; for (var i = 0, l = breakPoints.length; i < l; i++) { - var isLast = i === l - 1; - var start = breakPoints[i]; - var end = breakPoints[ isLast ? 0 : i + 1]; + isLast = i === l - 1; + start = breakPoints[i]; + end = breakPoints[ isLast ? 0 : i + 1]; + resultContour.push({ x: start.x, y: start.y, @@ -38,23 +47,44 @@ define( var curvePoints = data.slice(start.index, end.index + 1); } - if (curvePoints.length > 50) { - curvePoints = curvePoints.filter(function (p) { - return p.index % 10 === 0; + var bezierCurvePoints = []; + var curvePointsLast = curvePoints.length - 1; + if (curvePoints.length > 60) { + bezierCurvePoints = curvePoints.filter(function (p, index) { + return index === 0 || index === curvePointsLast || p.index % 6 === 0; + }); + } + else if (curvePoints.length > 30) { + bezierCurvePoints = curvePoints.filter(function (p, index) { + return index === 0 || index === curvePointsLast || p.index % 3 === 0; + }); + } + else { + bezierCurvePoints = curvePoints.filter(function (p, index) { + return index === 0 || index === curvePointsLast || p.index % 2 === 0; }); } - - - if (curvePoints.length > 6) { - var bezierCurve = fitBezier(curvePoints, 10); - if (bezierCurve.length) { - bezierCurve.forEach(function (p) { - resultContour.push(p); - }); - } + ///console.log(bezierCurvePoints.length); + var bezierCurve = fitBezier(bezierCurvePoints, 10, lasttHat); + if (bezierCurve.length) { + bezierCurve.forEach(function (p) { + resultContour.push(p); + }); + end = bezierCurve[bezierCurve.length - 1]; + end.tangency = true; } } + + if (end.tangency || end.inflexion) { + lasttHat = vector.normalize({ + x: end.x - start.x, + y: end.y - start.y + }); + } + else { + lasttHat = null; + } } resultContour = pathUtil.scale(resultContour, 0.1); diff --git a/src/graphics/image/findBreakPoints.js b/src/graphics/image/findBreakPoints.js index 6279c7d..83c5845 100644 --- a/src/graphics/image/findBreakPoints.js +++ b/src/graphics/image/findBreakPoints.js @@ -23,29 +23,80 @@ define( var THETA_TANGENCY = 0.1; // 相切抑制 var THETA_CORNER = 0.5; // 拐点抑制 var THETA_MARK_COUNT = 0.8; // 标记点个数抑制 + var THETA_INFLEXION_RANGE = 0.05; // 切线点之间的距离抑制 function isLine(p0, p1, p) { - return 1 - Math.abs(getCos(p.x - p0.x, p.y - p0.y, p.x - p1.x, p.y - p1.y)) < 0.005; + return 1 - Math.abs(getCos(p.x - p0.x, p.y - p0.y, p.x - p1.x, p.y - p1.y)) < 0.001; } - function removeOnLinePoint(contour) { + function removeOnLinePoint(points) { // 移除直线上误判的点 - for (var i = contour.length - 1, last = i; i >= 0; i--) { + for (var i = points.length - 1, last = i; i >= 0; i--) { // 这里注意逆序 - var p = contour[i]; - var next = i === last ? contour[0] : contour[i + 1]; - var prev = i === 0 ? contour[last] : contour[i - 1]; + var p = points[i]; + var next = i === last ? points[0] : points[i + 1]; + var prev = i === 0 ? points[last] : points[i - 1]; if (isLine(prev, next, p)) { - contour.splice(i, 1); + points.splice(i, 1); last--; continue; } } - return contour; + return points; } + function removeInflexionPoint(points, contour) { + // 移除过多的切线点 + var contourSize = contour.length; + var range; + for (var i = points.length - 1, last = i; i >= 0; i--) { + // 这里注意逆序 + var p = points[i]; + var next = i === last ? points[0] : points[i + 1]; + var prev = i === 0 ? points[last] : points[i - 1]; + + // 两个同为切线点 + if (p.inflexion && next.inflexion) { + range = i === last ? last + 1 - p.index + next.index : next.index - p.index; + if (range / contourSize < THETA_INFLEXION_RANGE) { + if (p.absTheta > next.absTheta) { + points.splice(i, 1); + } + else { + points.splice(i + 1, 1); + } + last--; + continue; + } + } + // 拐点附近的切线点 + else if (p.breakPoint && next.inflexion) { + range = i === last ? last + 1 - p.index + next.index : next.index - p.index; + if (range / contourSize < THETA_INFLEXION_RANGE) { + points.splice(i + 1, 1); + i--; + last--; + continue; + } + } + // 拐点附近的切线点 + else if (p.inflexion && next.breakPoint) { + range = i === last ? last + 1 - p.index + next.index : next.index - p.index; + if (range / contourSize < THETA_INFLEXION_RANGE) { + points.splice(i, 1); + i--; + last--; + continue; + } + } + } + + return points; + } + + /** * 对轮廓中的关键点做进一步提取 * @@ -57,43 +108,60 @@ define( var contourSize = contour.length; breakPoints = removeOnLinePoint(breakPoints); + breakPoints = removeInflexionPoint(breakPoints, contour); for (var i = 0, l = breakPoints.length; i < l; i++) { var isLast = i === l - 1; var start = breakPoints[i]; var end = breakPoints[ isLast ? 0 : i + 1]; - // 中间点小于3个,则判断为直线 - var count = isLast ? l - end.index : end.index - start.index; - if (start.breakPoint && end.breakPoint && count < 10) { + // 中间点小于10个,则判断为直线 + var range = isLast ? l - start.index + end.index : end.index - start.index; + if (start.breakPoint && end.breakPoint && range < 10) { start.right = 1; end.left = 1; } else { // 判断中间点距离 - mid = contour[Math.floor((end.index + (isLast ? contourSize : start.index)) / 2)]; + if (isLast) { + mid = contour[Math.floor(start.index + (contourSize - start.index + end.index) / 2) % contourSize]; + } + else { + mid = contour[Math.floor((start.index + end.index) / 2)]; + } + if (start.x === 3690 && start.y === 4250) { + debugger; + } // 夹角接近直线 if (isLine(start, end, mid)) { + console.log(start); // 随机选取 几个点进行直线判断 - var startIndex = start.index + 10; - var endIndex = end.index - 1; + var startIndex = start.index; + var endIndex = end.index; if (isLast) { - startIndex = end.index + 10; - endIndex = l + startIndex.index; + startIndex = start.index; + endIndex = contourSize + end.index; } - + var step = Math.floor(Math.max((endIndex - startIndex) / 10, 4)); var lineFlag = true; - for (var j = startIndex; j < endIndex; j+= 10) { + + + for (var j = startIndex + step; j < endIndex; j += step) { if (!isLine(start, end, contour[j % contourSize])) { lineFlag = false; break; } } + if (lineFlag) { start.right = 1; end.left = 1; } + else { + start.right = 2; + end.left = 2; + } } // 标记待选曲线 else { @@ -103,8 +171,6 @@ define( } } - // 移除过多的切线点 - return breakPoints; } diff --git a/src/graphics/image/fitBezier.js b/src/graphics/image/fitBezier.js index 88359ca..a1a39dc 100644 --- a/src/graphics/image/fitBezier.js +++ b/src/graphics/image/fitBezier.js @@ -18,12 +18,12 @@ define( * * @return {Array} 结果点集 */ - function fitBezier(points, scale) { + function fitBezier(points, scale, tHat1) { scale = scale || 1; var size = points.length; - var maxError = 200; + var maxError = 10 * scale; - var cubicBezier = fitCurve(points, maxError); + var cubicBezier = fitCurve(points, maxError, tHat1); var start = points[0]; var result = []; for (var i = 0, l = cubicBezier.length; i < l; i += 3) { diff --git a/src/graphics/image/fitCurve.js b/src/graphics/image/fitCurve.js index 302edd9..d5885b1 100644 --- a/src/graphics/image/fitCurve.js +++ b/src/graphics/image/fitCurve.js @@ -519,15 +519,20 @@ define( * * @return {Array} 结果点集 */ - function fitCurve(points, error) { + function fitCurve(points, error, tHat1, tHat2) { var last = points.length - 1; - var tHat1 = computeLeftTangent(points, 0); - var tHat2 = computeRightTangent(points, last); + if (!tHat1) { + var tHat1 = computeLeftTangent(points, 0); + } + if (!tHat2) { + var tHat2 = computeRightTangent(points, last); + } var result = []; fitCubic(points, 0, last, tHat1, tHat2, error, result); return result; } + fitCurve.normalize = normalize; return fitCurve; } diff --git a/src/graphics/vector.js b/src/graphics/vector.js index f481e80..5ebaf42 100644 --- a/src/graphics/vector.js +++ b/src/graphics/vector.js @@ -84,10 +84,24 @@ define( } + /** + * 将点转换成余弦值 + * + * @param {Object} p 点 + * @return {Object} 余弦值 + */ + function normalize(p) { + var factor = 1 / Math.sqrt(p.x * p.x + p.y * p.y); + p.x = p.x * factor; + p.y = p.y * factor; + return p; + } + return { getCos: getCos, getDist: getDist, - getDistPow: getDistPow + getDistPow: getDistPow, + normalize: normalize }; } );