modify contours fitting
This commit is contained in:
parent
1aa3f9ccfb
commit
d7d93aba8a
6
demo/data/image-contours13.js
Normal file
6
demo/data/image-contours13.js
Normal file
File diff suppressed because one or more lines are too long
6
demo/data/image-contours14.js
Normal file
6
demo/data/image-contours14.js
Normal file
File diff suppressed because one or more lines are too long
6
demo/data/image-contours15.js
Normal file
6
demo/data/image-contours15.js
Normal file
File diff suppressed because one or more lines are too long
@ -5,10 +5,10 @@
|
|||||||
|
|
||||||
define(
|
define(
|
||||||
function (require) {
|
function (require) {
|
||||||
var reducePoints = require('graphics/image/contour/douglasPeuckerReducePoints');
|
var reducePoints = require('graphics/image/contour/reducePoints');
|
||||||
var findBreakPoints = require('graphics/image/contour/findBreakPoints');
|
var findBreakPoints = require('graphics/image/contour/findBreakPoints');
|
||||||
var pathUtil = require('graphics/pathUtil');
|
var pathUtil = require('graphics/pathUtil');
|
||||||
var data = require('demo/../data/image-contours10');
|
var data = require('demo/../data/image-contours2');
|
||||||
|
|
||||||
|
|
||||||
var entry = {
|
var entry = {
|
||||||
@ -61,7 +61,7 @@ define(
|
|||||||
if (p.right == 1) {
|
if (p.right == 1) {
|
||||||
width = 'width: 4px;height: 4px';
|
width = 'width: 4px;height: 4px';
|
||||||
}
|
}
|
||||||
html += '<i data-index="'+ p.index +'" '+ (p.tangency ? 'data-tangency="1"' : '') + (p.visited ? 'data-visited="1"' : '') +' title="'+ p.theta +'" style="left:'+p.x+'px;top:'+p.y+'px;'+width+'" class="'+c+'"></i>';
|
html += '<i data-index="'+ p.index +'" '+ (p.ntiny || p.ptiny ? 'data-tiny="1"' : '') + (p.tangency ? 'data-tangency="1"' : '') + (p.visited ? 'data-visited="1"' : '') +' title="'+ p.theta +'" style="left:'+p.x+'px;top:'+p.y+'px;'+width+'" class="'+c+'"></i>';
|
||||||
}
|
}
|
||||||
|
|
||||||
$('#points-break').html(html);
|
$('#points-break').html(html);
|
||||||
|
@ -7,7 +7,7 @@ define(
|
|||||||
function (require) {
|
function (require) {
|
||||||
|
|
||||||
var fitContour = require('graphics/image/contour/fitContour');
|
var fitContour = require('graphics/image/contour/fitContour');
|
||||||
var data = require('demo/../data/image-contours10');
|
var data = require('demo/../data/image-contours5');
|
||||||
var drawPath = require('render/util/drawPath');
|
var drawPath = require('render/util/drawPath');
|
||||||
var pathUtil = require('graphics/pathUtil');
|
var pathUtil = require('graphics/pathUtil');
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ define(
|
|||||||
|
|
||||||
function reduce(contour, firstIndex, lastIndex, tolerance, splitArray) {
|
function reduce(contour, firstIndex, lastIndex, tolerance, splitArray) {
|
||||||
|
|
||||||
if (lastIndex - firstIndex <= 3) {
|
if (lastIndex - firstIndex < 3) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,12 +55,17 @@ define(
|
|||||||
|
|
||||||
if (splitArray.length) {
|
if (splitArray.length) {
|
||||||
splitArray.unshift(firstIndex);
|
splitArray.unshift(firstIndex);
|
||||||
return splitArray.map(function (index) {
|
splitArray = splitArray.map(function (index) {
|
||||||
contour[index].index = index;
|
contour[index].index = index;
|
||||||
return contour[index];
|
return contour[index];
|
||||||
}).sort(function (a, b) {
|
})
|
||||||
|
|
||||||
|
// 去除临近的点
|
||||||
|
|
||||||
|
splitArray.sort(function (a, b) {
|
||||||
return a.index - b.index;
|
return a.index - b.index;
|
||||||
});
|
});
|
||||||
|
return splitArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
return contour;
|
return contour;
|
||||||
|
@ -11,7 +11,7 @@ define(
|
|||||||
var vector = require('graphics/vector');
|
var vector = require('graphics/vector');
|
||||||
var getCos = vector.getCos;
|
var getCos = vector.getCos;
|
||||||
var getDist = vector.getDist;
|
var getDist = vector.getDist;
|
||||||
var THETA_CORNER = 0.8; // 拐点抑制
|
var THETA_CORNER = 1.0; // 拐点抑制
|
||||||
|
|
||||||
function dist(p0, p1) {
|
function dist(p0, p1) {
|
||||||
return Math.sqrt(Math.pow(p0.x - p1.x, 2) + Math.pow(p0.y - p1.y, 2));
|
return Math.sqrt(Math.pow(p0.x - p1.x, 2) + Math.pow(p0.y - p1.y, 2));
|
||||||
@ -27,132 +27,153 @@ define(
|
|||||||
contour = makeLink(contour);
|
contour = makeLink(contour);
|
||||||
|
|
||||||
var start = contour[0];
|
var start = contour[0];
|
||||||
var cur = start;
|
var longDist = 30 * scale;
|
||||||
var longDist = 80 * scale;
|
|
||||||
var shortDist = 20 * scale;
|
var shortDist = 20 * scale;
|
||||||
var lineDist = 10 * scale;
|
var lineDist = 10 * scale;
|
||||||
var tinyDist = 2 * scale;
|
var tinyDist = 3 * scale;
|
||||||
|
|
||||||
|
var cur = start;
|
||||||
do {
|
do {
|
||||||
|
|
||||||
|
cur.ndist = cur.next.pdist = dist(cur, cur.next);
|
||||||
|
|
||||||
// 距离比较近的点判断切角会不准确,需要特殊处理
|
// 距离比较近的点判断切角会不准确,需要特殊处理
|
||||||
if (Math.abs(cur.x - cur.next.x) <= tinyDist && Math.abs(cur.y - cur.next.y) <= tinyDist) {
|
if (Math.abs(cur.x - cur.next.x) <= tinyDist && Math.abs(cur.y - cur.next.y) <= tinyDist) {
|
||||||
cur.ntiny = true;
|
cur.ntiny = true;
|
||||||
cur.next.ptiny = true;
|
cur.next.ptiny = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var cos = getCos(
|
||||||
|
cur.ptiny ? cur.prev.prev : cur.prev,
|
||||||
|
cur,
|
||||||
|
cur.ntiny ? cur.next.next : cur.next
|
||||||
|
);
|
||||||
|
|
||||||
var cos = getCos(cur.ptiny ? cur.prev.prev : cur.prev, cur, cur.ntiny ? cur.next.next : cur.next);
|
|
||||||
cur.theta = Math.acos(cos > 1 ? 1 : cos) ;
|
cur.theta = Math.acos(cos > 1 ? 1 : cos) ;
|
||||||
|
|
||||||
if (cur.theta > THETA_CORNER) {
|
if (cur.theta > THETA_CORNER) {
|
||||||
cur.breakPoint = true;
|
cur.corner = true;
|
||||||
|
}
|
||||||
|
|
||||||
// 判断水平和竖直线
|
// 判断水平和竖直线
|
||||||
if (
|
if (
|
||||||
(Math.abs(cur.next.x - cur.x) < scale)
|
(Math.abs(cur.next.x - cur.x) < scale)
|
||||||
&& Math.abs(cur.next.y - cur.y) > lineDist
|
&& Math.abs(cur.next.y - cur.y) > lineDist
|
||||||
) {
|
) {
|
||||||
cur.next.vertical = true;
|
cur.next.vertical = true;
|
||||||
cur.vertical = true;
|
cur.vertical = true;
|
||||||
cur.right = 1;
|
}
|
||||||
}
|
else if (
|
||||||
else if (
|
(Math.abs(cur.next.y - cur.y) < scale)
|
||||||
(Math.abs(cur.next.y - cur.y) < scale)
|
&& Math.abs(cur.next.x - cur.x) > lineDist
|
||||||
&& Math.abs(cur.next.x - cur.x) > lineDist
|
) {
|
||||||
) {
|
cur.next.hoz = true;
|
||||||
cur.next.hoz = true;
|
cur.hoz = true;
|
||||||
cur.hoz = true;
|
|
||||||
cur.right = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 判断顶角
|
// 判断顶角
|
||||||
if(cur.x <= cur.prev.x && cur.x <= cur.next.x
|
if(cur.x <= cur.prev.x && cur.x <= cur.next.x) {
|
||||||
|| cur.y <= cur.prev.y && cur.y <= cur.next.y
|
cur.xTop = true;
|
||||||
) {
|
|
||||||
cur.apexTop = true;
|
|
||||||
cur.apex = true;
|
cur.apex = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cur.x >= cur.prev.x && cur.x >= cur.next.x
|
if(cur.y <= cur.prev.y && cur.y <= cur.next.y) {
|
||||||
|| cur.y >= cur.prev.y && cur.y >= cur.next.y
|
cur.yTop = true;
|
||||||
) {
|
|
||||||
cur.apexBottom = true;
|
|
||||||
cur.apex = true;
|
cur.apex = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 标记上一个点和下一个点的距离
|
if (cur.x >= cur.prev.x && cur.x >= cur.next.x) {
|
||||||
if (Math.abs(cur.x - cur.next.x) > longDist) {
|
cur.xBottom = true;
|
||||||
cur.nxl = true;
|
cur.apex = true;
|
||||||
cur.next.pxl = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Math.abs(cur.y - cur.next.y) > longDist) {
|
if (cur.y >= cur.prev.y && cur.y >= cur.next.y) {
|
||||||
cur.nyl = true;
|
cur.yBottom = true;
|
||||||
cur.next.pyl = true;
|
cur.apex = true;
|
||||||
}
|
|
||||||
|
|
||||||
if (Math.abs(cur.x - cur.next.x) < shortDist) {
|
|
||||||
cur.nxs = true;
|
|
||||||
cur.next.pxs = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Math.abs(cur.y - cur.next.y) < shortDist) {
|
|
||||||
cur.nys = true;
|
|
||||||
cur.next.pys = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cur = cur.next;
|
cur = cur.next;
|
||||||
} while (cur !== start);
|
} while (cur !== start);
|
||||||
|
|
||||||
cur = start;
|
cur = start;
|
||||||
|
// 判断角点和切线点
|
||||||
do {
|
do {
|
||||||
|
|
||||||
|
if (cur.visited) {
|
||||||
|
cur = cur.next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// 修正直角连接点的x,y坐标
|
// 修正直角连接点的x,y坐标
|
||||||
if (cur.breakPoint && cur.hoz && cur.vertical) {
|
if (cur.corner && cur.hoz && cur.vertical) {
|
||||||
cur.x = (Math.abs(cur.prev.x - cur.x) <= scale) ? cur.prev.x : cur.next.x;
|
cur.x = (Math.abs(cur.prev.x - cur.x) <= scale) ? cur.prev.x : cur.next.x;
|
||||||
cur.y = (Math.abs(cur.prev.y - cur.y) <= scale) ? cur.prev.y : cur.next.y;
|
cur.y = (Math.abs(cur.prev.y - cur.y) <= scale) ? cur.prev.y : cur.next.y;
|
||||||
cur.rightAngle = true;
|
cur.prev.right = 1;
|
||||||
|
cur.right = 1;
|
||||||
|
cur.visited = true;
|
||||||
|
cur.breakPoint = true;
|
||||||
|
}
|
||||||
|
// 判断单独的角点
|
||||||
|
else if (cur.corner) {
|
||||||
|
cur.visited = true;
|
||||||
|
cur.breakPoint = true;
|
||||||
|
}
|
||||||
|
// 判断单独的顶角切线点
|
||||||
|
else if (cur.apex && !cur.prev.apex && !cur.next.apex) {
|
||||||
|
if (cur.theta < 0.3) {
|
||||||
|
cur.tangency = true;
|
||||||
|
}
|
||||||
|
cur.visited = true;
|
||||||
|
cur.breakPoint = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断切线
|
// 判断边界点中的切线点
|
||||||
if(cur.theta < 0.1 && (cur.pxl || cur.pyl || cur.nxl || cur.nyl)) {
|
// else if (cur.theta < 0.3 && (cur.ndist > longDist || cur.pdist > longDist)) {
|
||||||
|
// cur.visited = true;
|
||||||
|
// cur.tangency = true;
|
||||||
|
// cur.breakPoint = true;
|
||||||
|
// }
|
||||||
|
// 判断边界点中的切线点
|
||||||
|
else if (cur.apex && (cur.ndist > longDist || cur.pdist > longDist)) {
|
||||||
|
cur.visited = true;
|
||||||
|
cur.breakPoint = true;
|
||||||
|
}
|
||||||
|
// 直线段
|
||||||
|
else if (cur.theta > 0.8 && (cur.ndist > longDist || cur.pdist > longDist)) {
|
||||||
|
cur.visited = true;
|
||||||
|
cur.breakPoint = true;
|
||||||
|
}
|
||||||
|
// 判断成对的顶角切线点
|
||||||
|
else if (cur.apex && cur.next.apex && cur.prev.theta < 0.4 && cur.next.theta < 0.4) {
|
||||||
|
// 修正切线点位置
|
||||||
|
if (cur.xTop && cur.next.xTop || cur.xBottom && cur.next.xBottom) {
|
||||||
|
var minus = Math.max(Math.floor(Math.abs(cur.next.y - cur.y) / 4), 4 * scale);
|
||||||
|
cur.y = cur.y > cur.next.y ? cur.y - minus : cur.y + minus;
|
||||||
|
cur.next.y = cur.next.y > cur.y ? cur.next.y - minus : cur.next.y + minus;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cur.yTop && cur.next.yTop || cur.yBottom && cur.next.yBottom) {
|
||||||
|
var minus = Math.max(Math.floor(Math.abs(cur.next.x - cur.x) / 4), 4 * scale);
|
||||||
|
cur.x = cur.x > cur.next.x ? cur.x - minus : cur.x + minus;
|
||||||
|
cur.next.x = cur.next.x > cur.x ? cur.next.x - minus : cur.next.x + minus;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur.visited = true;
|
||||||
cur.tangency = true;
|
cur.tangency = true;
|
||||||
}
|
cur.breakPoint = true;
|
||||||
|
cur.next.visited = true;
|
||||||
// 移除非真正的breakPoint
|
cur.next.tangency = true;
|
||||||
if (cur.breakPoint && !cur.ptiny && !cur.ntiny && (cur.nxs && cur.pxs)) {
|
cur.next.breakPoint = true;
|
||||||
delete cur.breakPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
cur = cur.next;
|
|
||||||
} while (cur !== start);
|
|
||||||
|
|
||||||
var breakPoints = [];
|
|
||||||
cur = start;
|
|
||||||
do {
|
|
||||||
|
|
||||||
if (cur.rightAngle) {
|
|
||||||
breakPoints.push(cur);
|
|
||||||
}
|
|
||||||
else if (cur.right === 1) {
|
|
||||||
breakPoints.push(cur);
|
|
||||||
}
|
|
||||||
else if (cur.ntiny || cur.rtiny) {
|
|
||||||
breakPoints.push(cur);
|
|
||||||
}
|
|
||||||
else if (cur.apex) {
|
|
||||||
breakPoints.push(cur);
|
|
||||||
}
|
|
||||||
else if (cur.pxl && cur.next.pxs || cur.pyl && cur.next.pys) {
|
|
||||||
breakPoints.push(cur);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cur = cur.next;
|
cur = cur.next;
|
||||||
} while (cur !== start);
|
} while (cur !== start);
|
||||||
|
|
||||||
|
var breakPoints = contour.filter(function (p) {
|
||||||
|
return p.breakPoint;
|
||||||
|
});
|
||||||
|
|
||||||
breakPoints.sort(function (a, b) {
|
breakPoints.sort(function (a, b) {
|
||||||
return a.index - b.index;
|
return a.index - b.index;
|
||||||
});
|
});
|
||||||
|
@ -21,7 +21,7 @@ define(
|
|||||||
function fitBezier(points, scale, tHat1, tHat2) {
|
function fitBezier(points, scale, tHat1, tHat2) {
|
||||||
scale = scale || 1;
|
scale = scale || 1;
|
||||||
var size = points.length;
|
var size = points.length;
|
||||||
var maxError = 10 * scale * scale;
|
var maxError = 4 * scale * scale;
|
||||||
|
|
||||||
var cubicBezier = fitCurve(points, maxError, tHat1, tHat2);
|
var cubicBezier = fitCurve(points, maxError, tHat1, tHat2);
|
||||||
var start = points[0];
|
var start = points[0];
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
define(
|
define(
|
||||||
function (require) {
|
function (require) {
|
||||||
|
|
||||||
var reducePoints = require('graphics/image/contour/douglasPeuckerReducePoints');
|
var reducePoints = require('graphics/image/contour/reducePoints');
|
||||||
var findBreakPoints = require('./findBreakPoints');
|
var findBreakPoints = require('./findBreakPoints');
|
||||||
var fitBezier = require('./fitBezier');
|
var fitBezier = require('./fitBezier');
|
||||||
var pathUtil = require('graphics/pathUtil');
|
var pathUtil = require('graphics/pathUtil');
|
||||||
@ -49,13 +49,11 @@ define(
|
|||||||
curvePoints = reducedData.slice(start.index, end.index + 1);
|
curvePoints = reducedData.slice(start.index, end.index + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (curvePoints.length <= 2) {
|
if (curvePoints.length <= 2) {
|
||||||
tHat1Point = end;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((start.inflexion || start.tangency) && tHat1Point) {
|
if (start.tangency && tHat1Point && start !== tHat1Point) {
|
||||||
tHat1 = vector.normalize({
|
tHat1 = vector.normalize({
|
||||||
x: start.x - tHat1Point.x,
|
x: start.x - tHat1Point.x,
|
||||||
y: start.y - tHat1Point.y
|
y: start.y - tHat1Point.y
|
||||||
@ -65,7 +63,7 @@ define(
|
|||||||
tHat1 = null;
|
tHat1 = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var bezierCurve = fitBezier(curvePoints, scale, tHat1);
|
var bezierCurve = fitBezier(curvePoints, scale);
|
||||||
if (bezierCurve.length) {
|
if (bezierCurve.length) {
|
||||||
bezierCurve.forEach(function (p) {
|
bezierCurve.forEach(function (p) {
|
||||||
if (!isNaN(p.x) && !isNaN(p.y)) {
|
if (!isNaN(p.x) && !isNaN(p.y)) {
|
||||||
@ -75,6 +73,9 @@ define(
|
|||||||
onCurve: p.onCurve
|
onCurve: p.onCurve
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
console.log('nan');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
end = bezierCurve[bezierCurve.length - 2];
|
end = bezierCurve[bezierCurve.length - 2];
|
||||||
@ -98,19 +99,19 @@ define(
|
|||||||
|
|
||||||
// 去除直线
|
// 去除直线
|
||||||
if (resultContour.length <= 2) {
|
if (resultContour.length <= 2) {
|
||||||
return null;
|
return [];
|
||||||
}
|
}
|
||||||
// 去除拟合后变成了直线轮廓
|
// 去除拟合后变成了直线轮廓
|
||||||
else if (
|
else if (
|
||||||
resultContour.length <= 4
|
resultContour.length <= 4
|
||||||
&& vector.getDist(resultContour[0], resultContour[1], resultContour[2]) < scale
|
&& vector.getDist(resultContour[0], resultContour[1], resultContour[2]) < scale
|
||||||
) {
|
) {
|
||||||
return null;
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
return pathUtil.deInterpolate(reducePath(resultContour).map(function (p) {
|
return pathUtil.deInterpolate(reducePath(resultContour).map(function (p) {
|
||||||
p.x = Math.floor(p.x);
|
p.x = Math.round(p.x);
|
||||||
p.y = Math.floor(p.y);
|
p.y = Math.round(p.y);
|
||||||
return p;
|
return p;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
97
src/graphics/image/contour/reducePoints.js
Normal file
97
src/graphics/image/contour/reducePoints.js
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
/**
|
||||||
|
* @file 消减点
|
||||||
|
* @author mengke01(kekee000@gmail.com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
define(
|
||||||
|
function (require) {
|
||||||
|
|
||||||
|
var douglasPeuckerReducePoints = require('graphics/image/contour/douglasPeuckerReducePoints');
|
||||||
|
var makeLink = require('graphics/pathUtil').makeLink;
|
||||||
|
var vector = require('graphics/vector');
|
||||||
|
var getCos = vector.getCos;
|
||||||
|
var getDist = vector.getDist;
|
||||||
|
|
||||||
|
function dist(p0, p1) {
|
||||||
|
return Math.sqrt(Math.pow(p0.x - p1.x, 2) + Math.pow(p0.y - p1.y, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消减非必要的点
|
||||||
|
*
|
||||||
|
* @param {Array} contour 轮廓点集
|
||||||
|
* @param {number} firstIndex 起始索引
|
||||||
|
* @param {number} lastIndex 结束索引
|
||||||
|
* @return {Array} 消减后的点集
|
||||||
|
*/
|
||||||
|
function reducePoints(contour, firstIndex, lastIndex, scale, tolerance) {
|
||||||
|
var points = douglasPeuckerReducePoints(contour, firstIndex, lastIndex, scale, tolerance);
|
||||||
|
points = makeLink(points);
|
||||||
|
|
||||||
|
var start = points[0];
|
||||||
|
var tinyDist = 3 * scale;
|
||||||
|
var shortDistance = 10 * scale;
|
||||||
|
var longDistance = 40 * scale;
|
||||||
|
var rightAngle = Math.PI / 2;
|
||||||
|
|
||||||
|
var cur = start;
|
||||||
|
|
||||||
|
do {
|
||||||
|
cur.ndist = cur.next.pdist = dist(cur, cur.next);
|
||||||
|
cur = cur.next;
|
||||||
|
} while (cur !== start);
|
||||||
|
|
||||||
|
|
||||||
|
cur = start;
|
||||||
|
do {
|
||||||
|
|
||||||
|
if (cur.visited) {
|
||||||
|
cur = cur.next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Math.abs(cur.x - cur.next.x) <= tinyDist && Math.abs(cur.y - cur.next.y) <= tinyDist) {
|
||||||
|
var theta = Math.acos(getCos(cur.x - cur.prev.x, cur.y - cur.prev.y, cur.next.next.x - cur.next.x, cur.next.next.y - cur.next.y)) || 1;
|
||||||
|
// 小于直角则考虑移除点
|
||||||
|
if (theta < rightAngle) {
|
||||||
|
// 顶角
|
||||||
|
if (
|
||||||
|
cur.x >= cur.prev.x && cur.x >= cur.next.x
|
||||||
|
|| cur.x <= cur.prev.x && cur.x <= cur.next.x
|
||||||
|
|| cur.y >= cur.prev.y && cur.y >= cur.next.y
|
||||||
|
|| cur.y <= cur.prev.y && cur.y <= cur.next.y
|
||||||
|
|
||||||
|
) {
|
||||||
|
cur.next.deleted = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cur.deleted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cur.visited = cur.next.visited = true;
|
||||||
|
}
|
||||||
|
// 一个点距离比较近一个非常远
|
||||||
|
else if (
|
||||||
|
cur.ndist > longDistance && cur.pdist < shortDistance
|
||||||
|
|| cur.pdist > longDistance && cur.ndist < shortDistance
|
||||||
|
&& getCos(cur.prev, cur, cur.next) > 0.9
|
||||||
|
) {
|
||||||
|
cur.deleted = true;
|
||||||
|
cur.visited = cur.next.visited = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur = cur.next;
|
||||||
|
} while (cur !== start);
|
||||||
|
|
||||||
|
|
||||||
|
return points.filter(function (p) {
|
||||||
|
delete p.visited;
|
||||||
|
return !p.deleted;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return reducePoints;
|
||||||
|
}
|
||||||
|
);
|
Loading…
x
Reference in New Issue
Block a user