fix bezier cross bugs
This commit is contained in:
@@ -10,8 +10,8 @@ define(
|
||||
function(require) {
|
||||
|
||||
var computeBoundingBox = require('render/util/computeBoundingBox');
|
||||
var isLineCross = require('render/util/isLineCross');
|
||||
var isBezierCross = require('render/util/isBezierCross');
|
||||
var isLineCross = require('render/util/isLineRayCross');
|
||||
var isBezierRayCross = require('render/util/isBezierRayCross');
|
||||
|
||||
var entry = {
|
||||
|
||||
@@ -24,18 +24,62 @@ define(
|
||||
var width = canvas.offsetWidth;
|
||||
var height = canvas.offsetHeight;
|
||||
|
||||
var points = [];
|
||||
[0, 1, 2, 3].forEach(function(i) {
|
||||
var p = {
|
||||
x: Math.floor(Math.random() * (width - 100) + 50),
|
||||
y: Math.floor(Math.random() * (height - 100) + 50)
|
||||
// var points = [];
|
||||
// [0, 1, 2, 3].forEach(function(i) {
|
||||
// var p = {
|
||||
// x: Math.floor(Math.random() * (width - 100) + 50),
|
||||
// y: Math.floor(Math.random() * (height - 100) + 50)
|
||||
// }
|
||||
// points[i] = p;
|
||||
// $($('.point').get(i)).css({
|
||||
// left: p.x,
|
||||
// top: p.y
|
||||
// });
|
||||
// });
|
||||
|
||||
var points = [
|
||||
{
|
||||
x: 130,
|
||||
y: 77
|
||||
},
|
||||
{
|
||||
x: 130,
|
||||
y: 148
|
||||
},
|
||||
{
|
||||
x: 65,
|
||||
y: 148
|
||||
},
|
||||
{
|
||||
x: 9,
|
||||
y: 133
|
||||
}
|
||||
points[i] = p;
|
||||
$($('.point').get(i)).css({
|
||||
left: p.x,
|
||||
top: p.y
|
||||
});
|
||||
});
|
||||
];
|
||||
|
||||
// var points = [
|
||||
// {
|
||||
// x: 65,
|
||||
// y: 148
|
||||
// },
|
||||
// {
|
||||
// x: 20,
|
||||
// y: 148
|
||||
// },
|
||||
// {
|
||||
// x: 5,
|
||||
// y: 115
|
||||
// },
|
||||
// {
|
||||
// x: 9,
|
||||
// y: 133
|
||||
// }
|
||||
// ];
|
||||
|
||||
|
||||
$('[data-index="3"]').css({
|
||||
left: points[3].x,
|
||||
top: points[3].y
|
||||
})
|
||||
|
||||
var point;
|
||||
|
||||
@@ -97,8 +141,10 @@ define(
|
||||
ctx.lineTo(max[0], min[1]);
|
||||
ctx.lineTo(min[0], min[1]);
|
||||
ctx.stroke();
|
||||
|
||||
console.log(isBezierCross(points[0], points[1], points[2], points[3]));
|
||||
//console.time('bezier');
|
||||
var r = isBezierRayCross(points[0], points[1], points[2], points[3]);
|
||||
//console.timeEnd('bezier');
|
||||
console.log(r);
|
||||
}
|
||||
|
||||
draw();
|
||||
|
||||
@@ -30,8 +30,9 @@ define(
|
||||
render.camera.ratio = 1;
|
||||
});
|
||||
|
||||
render.capture.on('dragstart', function(e) {
|
||||
render.capture.on('down', function(e) {
|
||||
var shape = render.painter.getShapeIn(e);
|
||||
|
||||
if(shape) {
|
||||
render.selectedShape = shape;
|
||||
}
|
||||
|
||||
@@ -22,8 +22,8 @@ define(
|
||||
*/
|
||||
getRect: function(shape) {
|
||||
return {
|
||||
x: shape.x,
|
||||
y: shape.y,
|
||||
x: shape.x - shape.width / 2 ,
|
||||
y: shape.y - shape.height / 2,
|
||||
width: shape.width,
|
||||
height: shape.height
|
||||
};
|
||||
@@ -38,10 +38,12 @@ define(
|
||||
* @param {boolean} 是否
|
||||
*/
|
||||
isIn: function(shape, x, y) {
|
||||
return x <= shape.x + shape.width
|
||||
&& x >= shape.x
|
||||
&& y <= shape.y + shape.height
|
||||
&& y >= shape.y;
|
||||
var w = shape.width / 2;
|
||||
var h = shape.height / 2;
|
||||
return x <= shape.x + w
|
||||
&& x >= shape.x - w
|
||||
&& y <= shape.y + h
|
||||
&& y >= shape.y - h;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -51,13 +53,13 @@ define(
|
||||
* @param {Object} shape shape数据
|
||||
*/
|
||||
draw: function(ctx, shape) {
|
||||
var w = shape.width;
|
||||
var h = shape.height;
|
||||
ctx.moveTo(shape.x, shape.y);
|
||||
ctx.lineTo(shape.x + w, shape.y);
|
||||
var w = shape.width / 2;
|
||||
var h = shape.height / 2;
|
||||
ctx.moveTo(shape.x - w, shape.y - h);
|
||||
ctx.lineTo(shape.x + w, shape.y - h);
|
||||
ctx.lineTo(shape.x + w, shape.y + h);
|
||||
ctx.lineTo(shape.x, shape.y + h);
|
||||
ctx.lineTo(shape.x, shape.y);
|
||||
ctx.lineTo(shape.x - w, shape.y + h);
|
||||
ctx.lineTo(shape.x - w, shape.y - h);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -3,91 +3,20 @@
|
||||
* @author mengke01
|
||||
* @date
|
||||
* @description
|
||||
* 判断x轴射线是否与贝塞尔曲线相交
|
||||
* 求两个bezier曲线的交点
|
||||
*/
|
||||
|
||||
|
||||
define(
|
||||
function(require) {
|
||||
|
||||
var computeBoundingBox = require('./computeBoundingBox');
|
||||
|
||||
|
||||
/**
|
||||
* 判断x轴射线是否与贝塞尔曲线相交
|
||||
*
|
||||
* @return {boolean} 是否
|
||||
* 求两个bezier曲线的交点
|
||||
*/
|
||||
function isBezierCross(p0, p1, p2, p) {
|
||||
|
||||
// 3点都在同一侧
|
||||
if(!((p0.y > p.y) + (p1.y > p.y) + (p2.y > p.y)) % 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var bound = computeBoundingBox.quadraticBezier(p0, p1, p2);
|
||||
|
||||
// 在包围盒内部
|
||||
if(
|
||||
p.x < bound.x + bound.width
|
||||
& p.y > bound.y && p.y < bound.y + bound.height
|
||||
) {
|
||||
var a = p0.y + p2.y - 2 * p1.y;
|
||||
var b = 2 * (p1.y - p0.y);
|
||||
var c = p0.y - p.y;
|
||||
// 求解二次方程
|
||||
var b4ac = Math.pow(b, 2) - 4 * a *c;
|
||||
|
||||
// 有解
|
||||
if(b4ac >= 0) {
|
||||
|
||||
var t1 = (-b + Math.sqrt(b4ac, 2)) / 2 / a;
|
||||
var t2 = (-b - Math.sqrt(b4ac, 2)) / 2 / a;
|
||||
|
||||
|
||||
var t = 0;
|
||||
var x1, x2;
|
||||
|
||||
// 两个交点
|
||||
if(t1 >= 0 && t1 <= 1) {
|
||||
t = t1;
|
||||
x1 = Math.pow(1 - t, 2) * p0.x
|
||||
+ 2 * t * (1-t) * p1.x
|
||||
+ Math.pow(t, 2) * p2.x;
|
||||
}
|
||||
|
||||
if(t2 >= 0 && t2 <= 1) {
|
||||
t = t2;
|
||||
x2 = Math.pow(1 - t, 2) * p0.x
|
||||
+ 2 * t * (1-t) * p1.x
|
||||
+ Math.pow(t, 2) * p2.x;
|
||||
}
|
||||
|
||||
if (x1 != undefined && x2 != undefined) {
|
||||
// 点在两个交点中间
|
||||
if(! (p.x > x1) ^ (p.x < x2) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if(x1 != undefined) {
|
||||
if(p.x < x1) {
|
||||
return {
|
||||
x: x1,
|
||||
y: p.y
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(x2 != undefined) {
|
||||
if(p.x < x2) {
|
||||
return {
|
||||
x: x2,
|
||||
y: p.y
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
function(p0, p1, p2, t0, t1. t2) {
|
||||
// a = p0 + p2 - 2p1
|
||||
// b = 2(p1 - p0)
|
||||
// c = p0
|
||||
}
|
||||
|
||||
|
||||
|
||||
121
src/render/util/isBezierRayCross.js
Normal file
121
src/render/util/isBezierRayCross.js
Normal file
@@ -0,0 +1,121 @@
|
||||
/**
|
||||
* @file isBezierCross.js
|
||||
* @author mengke01
|
||||
* @date
|
||||
* @description
|
||||
* 判断x轴射线是否与贝塞尔曲线相交
|
||||
*/
|
||||
|
||||
|
||||
define(
|
||||
function(require) {
|
||||
|
||||
var computeBoundingBox = require('./computeBoundingBox');
|
||||
|
||||
/**
|
||||
* 判断x轴射线是否与贝塞尔曲线相交
|
||||
*
|
||||
* @return {boolean} 是否
|
||||
*/
|
||||
function isBezierCross(p0, p1, p2, p) {
|
||||
|
||||
// 3点都在同一侧
|
||||
if(!((p0.y > p.y) + (p1.y > p.y) + (p2.y > p.y)) % 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var bound = computeBoundingBox.quadraticBezier(p0, p1, p2);
|
||||
|
||||
// 退化成线段
|
||||
if(bound.width == 0) {
|
||||
return ! (p.y > p0.y) ^ (p.y < p2.y)
|
||||
? {
|
||||
x: p0.x,
|
||||
y: p.y
|
||||
}
|
||||
: false;
|
||||
}
|
||||
// 判断是否在曲线上
|
||||
else if (bound.height == 0) {
|
||||
return p.y == p0.y && (p.x < p0.x || p.x < p2.x)
|
||||
? p
|
||||
: false;
|
||||
}
|
||||
|
||||
// 在包围盒内部
|
||||
if(
|
||||
p.x < bound.x + bound.width
|
||||
& p.y > bound.y && p.y < bound.y + bound.height
|
||||
) {
|
||||
var a = p0.y + p2.y - 2 * p1.y;
|
||||
var b = 2 * (p1.y - p0.y);
|
||||
var c = p0.y - p.y;
|
||||
var t1;
|
||||
var t2;
|
||||
|
||||
// 只有一个解
|
||||
if(a == 0) {
|
||||
t1 = -c / b;
|
||||
t2 = -1;
|
||||
}
|
||||
else {
|
||||
var b4ac = Math.pow(b, 2) - 4 * a *c;
|
||||
// 求解二次方程
|
||||
if(b4ac >= 0) {
|
||||
t1 = (-b + Math.sqrt(b4ac, 2)) / 2 / a;
|
||||
t2 = (-b - Math.sqrt(b4ac, 2)) / 2 / a;
|
||||
}
|
||||
}
|
||||
|
||||
var t = 0;
|
||||
var x1, x2;
|
||||
|
||||
// 两个交点
|
||||
if(t1 >= 0 && t1 <= 1) {
|
||||
t = t1;
|
||||
x1 = Math.pow(1 - t, 2) * p0.x
|
||||
+ 2 * t * (1-t) * p1.x
|
||||
+ Math.pow(t, 2) * p2.x;
|
||||
}
|
||||
|
||||
if(t2 >= 0 && t2 <= 1) {
|
||||
t = t2;
|
||||
x2 = Math.pow(1 - t, 2) * p0.x
|
||||
+ 2 * t * (1-t) * p1.x
|
||||
+ Math.pow(t, 2) * p2.x;
|
||||
}
|
||||
|
||||
if (x1 != undefined && x2 != undefined) {
|
||||
// 点在两个交点中间
|
||||
if(! (p.x > x1) ^ (p.x < x2) ) {
|
||||
return p.x > x1
|
||||
? {x: x2, y: p.y}
|
||||
: {x: x1, y: p.y};
|
||||
}
|
||||
}
|
||||
else if(x1 != undefined) {
|
||||
if(p.x < x1) {
|
||||
return {
|
||||
x: x1,
|
||||
y: p.y
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(x2 != undefined) {
|
||||
if(p.x < x2) {
|
||||
return {
|
||||
x: x2,
|
||||
y: p.y
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return isBezierCross;
|
||||
}
|
||||
);
|
||||
@@ -11,8 +11,8 @@
|
||||
|
||||
define(
|
||||
function(require) {
|
||||
var isBezierCross = require('./isBezierCross');
|
||||
var isLineCross = require('./isLineCross');
|
||||
var isBezierCross = require('./isBezierRayCross');
|
||||
var isLineCross = require('./isLineRayCross');
|
||||
|
||||
/**
|
||||
* 判断点是否在path内部
|
||||
|
||||
@@ -38,7 +38,10 @@ define(
|
||||
|
||||
var xcross = (p.y - p0.y) / (p1.y - p0.y) * (p1.x - p0.x) + p0.x;
|
||||
if (xcross > p.x) {
|
||||
return true;
|
||||
return {
|
||||
x: xcross,
|
||||
y: p.y
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user