add path overlap
This commit is contained in:
parent
2302a3773f
commit
247ad85643
47
src/graphics/isOnPath.js
Normal file
47
src/graphics/isOnPath.js
Normal file
@ -0,0 +1,47 @@
|
||||
/**
|
||||
* @file isOnPath.js
|
||||
* @author mengke01
|
||||
* @date
|
||||
* @description
|
||||
* 判断点是否在路径上
|
||||
*/
|
||||
|
||||
|
||||
define(
|
||||
function(require) {
|
||||
|
||||
|
||||
var pathIterator = require('./pathIterator');
|
||||
var getBezierQ2T = require('math/getBezierQ2T');
|
||||
|
||||
/**
|
||||
* 判断点是否在path上
|
||||
*
|
||||
* @param {Object} path path对象
|
||||
* @param {Object} p 点对象
|
||||
* @return {boolean|number} 是否在path上,如果在的话,返回起点索引号
|
||||
*/
|
||||
function isOnPath(path, p) {
|
||||
var zCount = false;
|
||||
pathIterator(path, function (c, p0, p1, p2, i) {
|
||||
if (c === 'L') {
|
||||
if (Math.abs((p.y - p0.y) * (p.x - p1.x) - (p.y - p1.y) * (p.x - p0.x)) <= 0.001) {
|
||||
zCount = i;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if(c === 'Q') {
|
||||
if (false !== getBezierQ2T(p0, p1, p2, p)) {
|
||||
zCount = i;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return zCount;
|
||||
}
|
||||
|
||||
|
||||
return isOnPath;
|
||||
}
|
||||
);
|
@ -12,6 +12,7 @@ define(
|
||||
var getPathJoint = require('./join/getPathJoint');
|
||||
var isInsidePath = require('./isInsidePath');
|
||||
var isBoundingBoxCross = require('./isBoundingBoxCross');
|
||||
var util = require('./util');
|
||||
|
||||
/**
|
||||
* 判断x轴射线是否穿过线段
|
||||
@ -22,14 +23,13 @@ define(
|
||||
*
|
||||
* 2: path0 包含 path1
|
||||
* 3: path1 包含 path0
|
||||
* 4: 重叠
|
||||
*/
|
||||
function isPathCross(path0, path1, bound0, bound1) {
|
||||
bound0 = bound0 || computeBoundingBox.computePath(path0);
|
||||
bound1 = bound1 || computeBoundingBox.computePath(path1);
|
||||
|
||||
var boundCross = isBoundingBoxCross(bound0, bound1);
|
||||
|
||||
if (boundCross) {
|
||||
if (isBoundingBoxCross(bound0, bound1)) {
|
||||
var result = getPathJoint(path0, path1);
|
||||
if (!result) {
|
||||
// 0 包含 1
|
||||
@ -42,7 +42,7 @@ define(
|
||||
}
|
||||
}
|
||||
else {
|
||||
return result;
|
||||
return util.removeOverlap(result);
|
||||
}
|
||||
}
|
||||
|
||||
|
100
src/graphics/isPathOverlap.js
Normal file
100
src/graphics/isPathOverlap.js
Normal file
@ -0,0 +1,100 @@
|
||||
/**
|
||||
* @file isPathOverlap.js
|
||||
* @author mengke01
|
||||
* @date
|
||||
* @description
|
||||
* 路径是否重叠
|
||||
*/
|
||||
|
||||
|
||||
define(
|
||||
function(require) {
|
||||
var computeBoundingBox = require('./computeBoundingBox');
|
||||
var isOnPath = require('./isOnPath');
|
||||
var isBoundingBoxCross = require('./isBoundingBoxCross');
|
||||
var getPointHash = require('./util').getPointHash;
|
||||
var pathIterator = require('./pathIterator');
|
||||
var getPoint = require('math/getBezierQ2Point');
|
||||
|
||||
function isPathPointsOverlap(path0, path1) {
|
||||
var hash = {};
|
||||
path1.forEach(function(p) {
|
||||
hash[getPointHash(p)] = true;
|
||||
});
|
||||
|
||||
var overlapCount = 0;
|
||||
path0.forEach(function(p) {
|
||||
if (hash[getPointHash(p)]) {
|
||||
overlapCount++;
|
||||
}
|
||||
});
|
||||
|
||||
return overlapCount === path0.length;
|
||||
}
|
||||
|
||||
function isPathPointsOn(path0, path1) {
|
||||
var zCount = 0;
|
||||
var length = path1.length;
|
||||
pathIterator(path0, function (c, p0, p1, p2) {
|
||||
if (c === 'L') {
|
||||
|
||||
// 这里需要判断,直线重叠的情况
|
||||
// TODO 需要判断是否是直线重叠,这里没有做判断
|
||||
var i0 = isOnPath(path1, p0);
|
||||
var i1 = isOnPath(path1, p1);
|
||||
if (false === i0 || false === i1 || i0 !== i1) {
|
||||
return false;
|
||||
}
|
||||
zCount++;
|
||||
}
|
||||
else if(c === 'Q') {
|
||||
// 这里需要判断,bezier曲线重叠的情况
|
||||
// 需要判断是否是bezier曲线重叠,这里没有做判断
|
||||
var i0 = isOnPath(path1, p0);
|
||||
var i1 = isOnPath(path1, p2);
|
||||
var i2 = isOnPath(path1, getPoint(p0, p1, p2, 0.5));
|
||||
if (false === i0 || false === i1 || false === i2) {
|
||||
return false;
|
||||
}
|
||||
zCount++;
|
||||
}
|
||||
});
|
||||
|
||||
return zCount === path0.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断路径是否重叠,需要注意的是,路径应该是经过插值之后的,否则会出现判断错误
|
||||
*
|
||||
* @return {boolean} 是否重叠
|
||||
*/
|
||||
function isPathOverlap(path0, path1, bound0, bound1) {
|
||||
bound0 = bound0 || computeBoundingBox.computePath(path0);
|
||||
bound1 = bound1 || computeBoundingBox.computePath(path1);
|
||||
|
||||
if (isBoundingBoxCross(bound0, bound1)) {
|
||||
|
||||
// 按点个数排下序
|
||||
if (path1.length < path0.length) {
|
||||
var tmp = path1;
|
||||
path1 = path0;
|
||||
path0 = tmp;
|
||||
}
|
||||
|
||||
// 是否点重叠
|
||||
if (isPathPointsOverlap(path0, path1) || isPathPointsOverlap(path1, path0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 是否点都在另一路径上
|
||||
if (isPathPointsOn(path0, path1) || isPathPointsOn(path1, path0)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return isPathOverlap;
|
||||
}
|
||||
);
|
@ -12,6 +12,7 @@ define(
|
||||
|
||||
var isPathCross = require('../isPathCross');
|
||||
var isInsidePath = require('../isInsidePath');
|
||||
//var isPathOverlap = require('../isPathOverlap');
|
||||
var getBezierQ2Point = require('math/getBezierQ2Point');
|
||||
var util = require('../util');
|
||||
var Relation = require('./relation');
|
||||
@ -27,13 +28,18 @@ define(
|
||||
* @return {boolean} 是否相交
|
||||
*/
|
||||
function getPathCross(path, splitedPath) {
|
||||
|
||||
// if (isPathOverlap(splitedPath, path)) {
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
var inPath = isInsidePath(
|
||||
path,
|
||||
splitedPath[1].onCurve
|
||||
? splitedPath[1]
|
||||
: getBezierQ2Point(splitedPath[0], splitedPath[1], splitedPath[2], 0.5)
|
||||
);
|
||||
return !!inPath;
|
||||
return inPath ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -67,7 +73,9 @@ define(
|
||||
var inPath = false;
|
||||
var partInPath = false;
|
||||
var inPathBefore = -1;
|
||||
// 求path0的分割曲线
|
||||
var isOverlap = false;
|
||||
|
||||
// 判断path0的相交情况
|
||||
splitedPaths0 = splitedPaths0.map(function(splitedPath) {
|
||||
|
||||
splitedPath.cross = getPathCross(path1, splitedPath);
|
||||
@ -76,15 +84,13 @@ define(
|
||||
inPath = true;
|
||||
}
|
||||
|
||||
if (2 === splitedPath.cross) {
|
||||
isOverlap = true;
|
||||
}
|
||||
|
||||
// 这里需要判断整个曲线有相交区域,但是部分曲线只有交点没有相交轮廓的情况
|
||||
if (inPathBefore === splitedPath.cross) {
|
||||
if (false === inPathBefore) {
|
||||
partInPath = true;
|
||||
}
|
||||
else {
|
||||
// 这里需要修正相交边缘重叠的情况,不然组合路径的时候会出问题
|
||||
// TODO
|
||||
}
|
||||
if (inPathBefore === splitedPath.cross && 0 === inPathBefore) {
|
||||
partInPath = true;
|
||||
}
|
||||
|
||||
|
||||
@ -115,13 +121,22 @@ define(
|
||||
console.warn('part cross');
|
||||
}
|
||||
else {
|
||||
// 这里只需要判断第一个就可以知道曲线相交情况了
|
||||
inPath = getPathCross(path0, splitedPaths1[0]);
|
||||
splitedPaths1 = splitedPaths1.map(function(path) {
|
||||
path.cross = inPath;
|
||||
inPath = !inPath;
|
||||
return path;
|
||||
});
|
||||
// 没有重叠的部分只需要判断第一个就可以知道曲线相交情况了
|
||||
if (!isOverlap) {
|
||||
inPath = getPathCross(path0, splitedPaths1[0]);
|
||||
splitedPaths1 = splitedPaths1.map(function(path) {
|
||||
path.cross = inPath;
|
||||
inPath = !inPath;
|
||||
return path;
|
||||
});
|
||||
}
|
||||
else {
|
||||
// 判断path1的相交情况
|
||||
splitedPaths1 = splitedPaths1.map(function(splitedPath) {
|
||||
splitedPath.cross = getPathCross(path0, splitedPath);
|
||||
return splitedPath;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//异向的 combine 等于相切
|
||||
|
@ -90,7 +90,7 @@ define(
|
||||
|
||||
for (var i = 0; i < splitedPaths0.length; i++) {
|
||||
var curPath = splitedPaths0[i];
|
||||
var cross = curPath.cross; // 起始cross
|
||||
var cross = !!curPath.cross; // 起始cross
|
||||
var length = curPath.length;
|
||||
|
||||
// 对于求相切的情况,外轮廓不需要处理,内轮廓需要根据另一个轮廓的方向调整反向
|
||||
@ -109,12 +109,13 @@ define(
|
||||
|
||||
var paths = nextHash[hashcode(end)];
|
||||
|
||||
// 选取异向
|
||||
// 这里如果是相交或者合并的情况,不需要处理,如果是相切的情况则需要取反向的曲线
|
||||
var p = paths[0];
|
||||
if (relation === Relation.tangency && cross == p.cross && paths.length > 1) {
|
||||
if (relation === Relation.tangency && cross == !!p.cross && paths.length > 1) {
|
||||
p = paths[1];
|
||||
}
|
||||
|
||||
// 选取异向
|
||||
if (end.x == p[0].x && end.y == p[0].y) {
|
||||
}
|
||||
else {
|
||||
|
@ -110,11 +110,42 @@ define(
|
||||
: zCount < 0 ? 1 : -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取点的hash
|
||||
*
|
||||
* @return {number} 哈希值
|
||||
*/
|
||||
function getPointHash(p) {
|
||||
return (p.x * 31 + p.y) * 31 + (p.onCurve ? 1 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除重复点
|
||||
*
|
||||
* @param {Array} points 点集合
|
||||
* @return {Array} 移除后点集合
|
||||
*/
|
||||
function removeOverlap(points) {
|
||||
var hash = {};
|
||||
var ret = [];
|
||||
for (var i = 0, l = points.length; i < l ; i++) {
|
||||
var hashcode = points[i].x * 31 + points[i].y;
|
||||
if (!hash[hashcode]) {
|
||||
ret.push(points[i]);
|
||||
hash[hashcode] = 1;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
return {
|
||||
ceil: ceil,
|
||||
ceilPoint: ceilPoint,
|
||||
isPointInBound: isPointInBound,
|
||||
isClockWise: isClockWise
|
||||
isClockWise: isClockWise,
|
||||
removeOverlap: removeOverlap,
|
||||
getPointHash: getPointHash
|
||||
};
|
||||
}
|
||||
);
|
Loading…
x
Reference in New Issue
Block a user