增加line cross
This commit is contained in:
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>二次贝塞尔曲线绘制</title>
|
||||
<script src="http://s1.bdstatic.com/r/www/cache/ecom/esl/1-8-2/esl.js"></script>
|
||||
<script src="http://libs.baidu.com/jquery/1.9.0/jquery.min.js"></script>
|
||||
<script src="./lib/esl.js"></script>
|
||||
<script src="./lib/jquery.min.js"></script>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
@@ -16,7 +16,6 @@
|
||||
height: 9px;
|
||||
margin-left: -5px;
|
||||
margin-top: -5px;
|
||||
background: #CCC;
|
||||
border: 1px solid red;
|
||||
}
|
||||
|
||||
@@ -39,8 +38,8 @@
|
||||
<div id="end-point" class="point" data-index="1"></div>
|
||||
<div id="control-point" class="point" data-index="2"></div>
|
||||
<div class="point" data-index="3"></div>
|
||||
<canvas id="canvas" width="500" height="500">
|
||||
</canvas>
|
||||
<div class="point" data-index="4"></div>
|
||||
<canvas id="canvas" width="500" height="500"></canvas>
|
||||
<script>
|
||||
require.config({
|
||||
baseUrl: '../src',
|
||||
@@ -51,6 +50,6 @@
|
||||
define('jquery', $);
|
||||
</script>
|
||||
|
||||
<script>require(['demo/quadraticBezier'])</script>
|
||||
<script>require(['demo/bezierSegmentCross'])</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>glyf查看</title>
|
||||
<script src="http://s1.bdstatic.com/r/www/cache/ecom/esl/1-8-2/esl.js"></script>
|
||||
<script src="http://libs.baidu.com/jquery/1.9.0/jquery.min.js"></script>
|
||||
<script src="./lib/esl.js"></script>
|
||||
<script src="./lib/jquery.min.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="./css/glyf.css">
|
||||
<style id="font-face"></style>
|
||||
</head>
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>glyf查看</title>
|
||||
<script src="http://s1.bdstatic.com/r/www/cache/ecom/esl/1-8-2/esl.js"></script>
|
||||
<script src="http://libs.baidu.com/jquery/1.9.0/jquery.min.js"></script>
|
||||
<script src="./lib/esl.js"></script>
|
||||
<script src="./lib/jquery.min.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="./css/glyf.css">
|
||||
<style id="font-face"></style>
|
||||
</head>
|
||||
|
||||
103
demo/js/bezierSegmentCross.js
Normal file
103
demo/js/bezierSegmentCross.js
Normal file
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* @file quadraticBezier.js
|
||||
* @author mengke01
|
||||
* @date
|
||||
* @description
|
||||
* 二次贝塞尔直线相交演示
|
||||
*/
|
||||
|
||||
define(
|
||||
function(require) {
|
||||
|
||||
var isBezierSegmentCross = require('graphics/isBezierSegmentCross');
|
||||
|
||||
var entry = {
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
init: function() {
|
||||
var canvas = $('#canvas').get(0);
|
||||
var ctx = canvas.getContext('2d');
|
||||
var width = canvas.offsetWidth;
|
||||
var height = canvas.offsetHeight;
|
||||
|
||||
var points = [
|
||||
{"x":163,"y":136},
|
||||
{"x":45,"y":54},
|
||||
{"x":124,"y":177},
|
||||
{"x":222,"y":122},
|
||||
{"x":57,"y":122}
|
||||
];
|
||||
|
||||
$('[data-index]').each(function(index, item) {
|
||||
$(item).css({
|
||||
left: points[index].x,
|
||||
top: points[index].y
|
||||
})
|
||||
});
|
||||
|
||||
var point;
|
||||
|
||||
$('.point').on('mousedown', function(e) {
|
||||
point = $(this);
|
||||
});
|
||||
|
||||
$(document.body).on('mousemove', onMove);
|
||||
$(document.body).on('mouseup', function(e) {
|
||||
onMove.call(this, e);
|
||||
point = null;
|
||||
});
|
||||
|
||||
function onMove(e) {
|
||||
var px = e.pageX;
|
||||
var py = e.pageY;
|
||||
if(point) {
|
||||
point.css({
|
||||
left: px,
|
||||
top: py
|
||||
});
|
||||
var p = points[+point.attr('data-index')];
|
||||
p.x = px;
|
||||
p.y = py;
|
||||
draw();
|
||||
}
|
||||
}
|
||||
|
||||
function draw() {
|
||||
|
||||
|
||||
ctx.clearRect(0, 0, width, height);
|
||||
//绘制2次贝塞尔曲线
|
||||
ctx.beginPath();
|
||||
ctx.strokeStyle='black';
|
||||
ctx.moveTo(points[0].x, points[0].y);
|
||||
ctx.quadraticCurveTo(points[1].x, points[1].y, points[2].x, points[2].y);
|
||||
ctx.moveTo(points[3].x, points[3].y);
|
||||
ctx.lineTo(points[4].x, points[4].y);
|
||||
ctx.lineWidth = 1;
|
||||
ctx.stroke();
|
||||
//console.time('bezier');
|
||||
var r = isBezierSegmentCross(points[0], points[1], points[2], points[3], points[4]);
|
||||
//console.timeEnd('bezier');
|
||||
console.log(r.length);
|
||||
|
||||
if(r) {
|
||||
ctx.beginPath();
|
||||
r.forEach(function(item) {
|
||||
ctx.moveTo(item.x, item.y);
|
||||
ctx.arc(item.x, item.y, 4, 0, Math.PI * 2, true);
|
||||
});
|
||||
ctx.fill();
|
||||
}
|
||||
}
|
||||
|
||||
draw();
|
||||
}
|
||||
};
|
||||
|
||||
entry.init();
|
||||
|
||||
return entry;
|
||||
}
|
||||
);
|
||||
@@ -24,19 +24,6 @@ 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)
|
||||
// }
|
||||
// points[i] = p;
|
||||
// $($('.point').get(i)).css({
|
||||
// left: p.x,
|
||||
// top: p.y
|
||||
// });
|
||||
// });
|
||||
|
||||
var points = [
|
||||
{
|
||||
x: 130,
|
||||
|
||||
99
demo/js/segmentCross.js
Normal file
99
demo/js/segmentCross.js
Normal file
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* @file quadraticBezier.js
|
||||
* @author mengke01
|
||||
* @date
|
||||
* @description
|
||||
* 二次贝塞尔直线相交演示
|
||||
*/
|
||||
|
||||
define(
|
||||
function(require) {
|
||||
|
||||
var isSegmentCross = require('graphics/isSegmentCross');
|
||||
|
||||
var entry = {
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
init: function() {
|
||||
var canvas = $('#canvas').get(0);
|
||||
var ctx = canvas.getContext('2d');
|
||||
var width = canvas.offsetWidth;
|
||||
var height = canvas.offsetHeight;
|
||||
|
||||
var points = [{"x":50,"y":200},{"x":97,"y":98},{"x":58,"y":94},{"x":105,"y":201}];
|
||||
|
||||
$('[data-index]').each(function(index, item) {
|
||||
$(item).css({
|
||||
left: points[index].x,
|
||||
top: points[index].y
|
||||
})
|
||||
});
|
||||
|
||||
var point;
|
||||
|
||||
$('.point').on('mousedown', function(e) {
|
||||
point = $(this);
|
||||
});
|
||||
|
||||
$(document.body).on('mousemove', onMove);
|
||||
$(document.body).on('mouseup', function(e) {
|
||||
onMove.call(this, e);
|
||||
point = null;
|
||||
});
|
||||
|
||||
function onMove(e) {
|
||||
var px = e.pageX;
|
||||
var py = e.pageY;
|
||||
if(point) {
|
||||
point.css({
|
||||
left: px,
|
||||
top: py
|
||||
});
|
||||
var p = points[+point.attr('data-index')];
|
||||
p.x = px;
|
||||
p.y = py;
|
||||
draw();
|
||||
}
|
||||
}
|
||||
|
||||
function draw() {
|
||||
|
||||
|
||||
ctx.clearRect(0, 0, width, height);
|
||||
//绘制2次贝塞尔曲线
|
||||
ctx.beginPath();
|
||||
ctx.strokeStyle='black';
|
||||
ctx.moveTo(points[0].x, points[0].y);
|
||||
ctx.lineTo(points[1].x, points[1].y);
|
||||
|
||||
ctx.moveTo(points[2].x, points[2].y);
|
||||
ctx.lineTo(points[3].x, points[3].y);
|
||||
|
||||
ctx.lineWidth = 1;
|
||||
ctx.stroke();
|
||||
//console.time('bezier');
|
||||
var r = isSegmentCross(points[0], points[1], points[2], points[3]);
|
||||
//console.timeEnd('bezier');
|
||||
console.log(r);
|
||||
|
||||
if(r) {
|
||||
ctx.beginPath();
|
||||
r.forEach(function(item) {
|
||||
ctx.moveTo(item.x, item.y);
|
||||
ctx.arc(item.x, item.y, 4, 0, Math.PI * 2, true);
|
||||
});
|
||||
ctx.fill();
|
||||
}
|
||||
}
|
||||
|
||||
draw();
|
||||
}
|
||||
};
|
||||
|
||||
entry.init();
|
||||
|
||||
return entry;
|
||||
}
|
||||
);
|
||||
1
demo/lib/esl.js
Normal file
1
demo/lib/esl.js
Normal file
File diff suppressed because one or more lines are too long
3
demo/lib/jquery.min.js
vendored
Normal file
3
demo/lib/jquery.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>测试render</title>
|
||||
<script src="http://s1.bdstatic.com/r/www/cache/ecom/esl/1-8-2/esl.js"></script>
|
||||
<script src="http://libs.baidu.com/jquery/1.9.0/jquery.min.js"></script>
|
||||
<script src="./lib/esl.js"></script>
|
||||
<script src="./lib/jquery.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>二次贝塞尔求交</title>
|
||||
<script src="http://s1.bdstatic.com/r/www/cache/ecom/esl/1-8-2/esl.js"></script>
|
||||
<script src="http://libs.baidu.com/jquery/1.9.0/jquery.min.js"></script>
|
||||
<script src="./lib/esl.js"></script>
|
||||
<script src="./lib/jquery.min.js"></script>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
@@ -16,7 +16,6 @@
|
||||
height: 9px;
|
||||
margin-left: -5px;
|
||||
margin-top: -5px;
|
||||
background: #CCC;
|
||||
border: 1px solid red;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>测试render</title>
|
||||
<script src="http://s1.bdstatic.com/r/www/cache/ecom/esl/1-8-2/esl.js"></script>
|
||||
<script src="http://libs.baidu.com/jquery/1.9.0/jquery.min.js"></script>
|
||||
<script src="./lib/esl.js"></script>
|
||||
<script src="./lib/jquery.min.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="./css/render.css">
|
||||
<style id="font-face"></style>
|
||||
</head>
|
||||
|
||||
45
demo/segmentCross.html
Normal file
45
demo/segmentCross.html
Normal file
@@ -0,0 +1,45 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>线段相交</title>
|
||||
<script src="./lib/esl.js"></script>
|
||||
<script src="./lib/jquery.min.js"></script>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.point {
|
||||
position: absolute;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
margin-left: -5px;
|
||||
margin-top: -5px;
|
||||
border: 1px solid red;
|
||||
}
|
||||
[data-index="0"], [data-index="1"] {
|
||||
border-color: green
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="point" data-index="0"></div>
|
||||
<div class="point" data-index="1"></div>
|
||||
<div class="point" data-index="2"></div>
|
||||
<div class="point" data-index="3"></div>
|
||||
<canvas id="canvas" width="500" height="500"></canvas>
|
||||
<script>
|
||||
require.config({
|
||||
baseUrl: '../src',
|
||||
paths: {
|
||||
demo: '../demo/js',
|
||||
}
|
||||
});
|
||||
define('jquery', $);
|
||||
</script>
|
||||
|
||||
<script>require(['demo/segmentCross'])</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -3,10 +3,13 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>font编辑器</title>
|
||||
<script src="http://s1.bdstatic.com/r/www/cache/ecom/esl/1-8-2/esl.js"></script>
|
||||
<script src="http://libs.baidu.com/jquery/1.9.0/jquery.min.js"></script>
|
||||
<script src="./lib/esl.js"></script>
|
||||
<script src="./lib/jquery.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<input id="upload-file" type="file">
|
||||
|
||||
<script>
|
||||
require.config({
|
||||
baseUrl: '../src',
|
||||
@@ -17,8 +20,6 @@
|
||||
define('jquery', $);
|
||||
</script>
|
||||
|
||||
<input id="upload-file" type="file">
|
||||
|
||||
<script>
|
||||
require(['demo/ttfparse']);
|
||||
</script>
|
||||
|
||||
@@ -14,45 +14,11 @@ define(
|
||||
var bezierQ2Equation = require('../math/bezierQ2Equation');
|
||||
var bezierQ4Equation = require('../math/bezierQ4Equation');
|
||||
var bezierCubeEquation = require('../math/bezierCubeEquation');
|
||||
|
||||
/**
|
||||
* 矩阵乘
|
||||
*
|
||||
* @param {Array.<number>} matrix 一维矩阵
|
||||
* @param {number} a 乘数算子
|
||||
* @return {Array.<number>} 数组
|
||||
*/
|
||||
function multi(matrix, a) {
|
||||
return matrix.map(function(item) {
|
||||
return item * a;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 矩阵减
|
||||
*
|
||||
* @param {Array.<number>} matrix1 一维矩阵
|
||||
* @param {Array.<number>} matrix2 一维矩阵
|
||||
* @return {Array.<number>} 数组
|
||||
*/
|
||||
function minus(matrix1, matrix2) {
|
||||
return matrix1.map(function(item, index) {
|
||||
return item - matrix2[index];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 矩阵加
|
||||
*
|
||||
* @param {Array.<number>} matrix1 一维矩阵
|
||||
* @param {Array.<number>} matrix2 一维矩阵
|
||||
* @return {Array.<number>} 数组
|
||||
*/
|
||||
function plus(matrix1, matrix2) {
|
||||
return matrix1.map(function(item, index) {
|
||||
return item + matrix2[index];
|
||||
});
|
||||
}
|
||||
|
||||
var matrix = require('./matrix');
|
||||
var multi = matrix.multi;
|
||||
var minus = matrix.minus;
|
||||
var plus = matrix.plus;
|
||||
|
||||
/**
|
||||
* 求两个bezier曲线的交点
|
||||
|
||||
@@ -9,21 +9,71 @@
|
||||
define(
|
||||
function(require) {
|
||||
|
||||
var bezierQ2Equation = require('../math/bezierQ2Equation');
|
||||
|
||||
/**
|
||||
* 判断贝塞尔曲线与直线相交
|
||||
*
|
||||
* @param {Object} p0 起点
|
||||
* @param {Object} p1 控制点
|
||||
* @param {Object} p2 终点
|
||||
* @param {Object} s1 直线点1
|
||||
* @param {Object} s2 直线点2
|
||||
* @param {Object} s0 直线点1
|
||||
* @param {Object} s1 直线点2
|
||||
* @return {boolean|Object} 是否相交
|
||||
*/
|
||||
function isBezierLineCross(p0, p1, p2, s1, s2) {
|
||||
function isBezierLineCross(p0, p1, p2, s0, s1) {
|
||||
|
||||
// y = kx + b
|
||||
// x = at^2 + bt + c
|
||||
// y = bt^2 + et + f
|
||||
// y = dt^2 + et + f
|
||||
//(ka-d)t^2 + (kb-e)t + (kc+b-f) = 0
|
||||
var result;
|
||||
|
||||
// 垂直x
|
||||
if (s0.y == s1.y) {
|
||||
result = bezierQ2Equation(
|
||||
p0.y + p2.y - 2 * p1.y,
|
||||
2 * (p1.y - p0.y),
|
||||
p0.y - s0.y
|
||||
);
|
||||
}
|
||||
else if (s0.x == s1.x) {
|
||||
result = bezierQ2Equation(
|
||||
p0.x + p2.x - 2 * p1.x,
|
||||
2 * (p1.x - p0.x),
|
||||
p0.x - s0.x
|
||||
);
|
||||
}
|
||||
else {
|
||||
|
||||
var k = (s1.y - s0.y) / (s1.x - s0.x);
|
||||
var b1 = s0.y - k * s0.x;
|
||||
|
||||
var a = p0.x + p2.x - 2 * p1.x;
|
||||
var b = 2 * (p1.x - p0.x);
|
||||
var c = p0.x;
|
||||
|
||||
var d = p0.y + p2.y - 2 * p1.y;
|
||||
var e = 2 * (p1.y - p0.y);
|
||||
var f = p0.y;
|
||||
|
||||
result = bezierQ2Equation(
|
||||
k * a - d,
|
||||
k * b - e,
|
||||
k * c + b1 - f
|
||||
);
|
||||
}
|
||||
|
||||
if(result) {
|
||||
return result.map(function(t) {
|
||||
return {
|
||||
x: p0.x * Math.pow(1 - t, 2) + 2 * p1.x * t * (1-t) + p2.x * Math.pow(t, 2),
|
||||
y: p0.y * Math.pow(1 - t, 2) + 2 * p1.y * t * (1-t) + p2.y * Math.pow(t, 2)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return isBezierLineCross;
|
||||
|
||||
@@ -8,19 +8,41 @@
|
||||
|
||||
define(
|
||||
function(require) {
|
||||
|
||||
var computeBoundingBox = require('./computeBoundingBox');
|
||||
var isBezierLineCross = require('./isBezierLineCross');
|
||||
var isBoundingBoxCross = require('./isBoundingBoxCross');
|
||||
var isPointInBound = require('./util').isPointInBound;
|
||||
|
||||
/**
|
||||
* 判断贝塞尔曲线与线段相交
|
||||
*
|
||||
* @param {Object} p0 起点
|
||||
* @param {Object} p1 控制点
|
||||
* @param {Object} p2 终点
|
||||
* @param {Object} s1 线段点1
|
||||
* @param {Object} s2 线段点2
|
||||
* @param {Object} s0 线段点1
|
||||
* @param {Object} s1 线段点2
|
||||
* @return {boolean|Object} 是否相交
|
||||
*/
|
||||
function isBezierSegmentCross(p0, p1, p2, s1, s2) {
|
||||
|
||||
function isBezierSegmentCross(p0, p1, p2, s0, s1) {
|
||||
var b1 = computeBoundingBox.quadraticBezier(p0, p1, p2);
|
||||
var bound = {
|
||||
x: Math.min(s0.x, s1.x),
|
||||
y: Math.min(s0.y, s1.y),
|
||||
width: Math.abs(s0.x - s1.x),
|
||||
height: Math.abs(s0.y - s1.y)
|
||||
};
|
||||
|
||||
if (isBoundingBoxCross(b1, bound)) {
|
||||
var result = isBezierLineCross(p0, p1, p2, s0, s1);
|
||||
if (result) {
|
||||
return result.filter(function(p) {
|
||||
return p.x >= s0.x && p.x <= s1.x
|
||||
|| p.x >= s1.x && p.x <= s0.x;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return isBezierSegmentCross;
|
||||
|
||||
@@ -9,18 +9,9 @@
|
||||
|
||||
define(
|
||||
function(require) {
|
||||
|
||||
/**
|
||||
* 判断点是否在bounding box内部
|
||||
*
|
||||
* @return {boolean} 是否
|
||||
*/
|
||||
function isPointInBounding(bound, p) {
|
||||
return p.x <= bound.x + bound.width
|
||||
&& p.x >= bound.x
|
||||
&& p.y <= bound.y + bound.height
|
||||
&& p.y >= bound.y
|
||||
}
|
||||
|
||||
var isPointInBound = require('./util').isPointInBound;
|
||||
|
||||
|
||||
/**
|
||||
* 两个boundingbox的关系
|
||||
@@ -30,20 +21,20 @@ define(
|
||||
* @return {number} 包含关系
|
||||
*/
|
||||
function isBoundingBoxCross(b1, b2) {
|
||||
var b1_lt = isPointInBounding(b2, b1); // 左上
|
||||
var b1_rt = isPointInBounding(b2, {x: b1.x + b1.width, y: b1.y}); // 右上
|
||||
var b1_lb = isPointInBounding(b2, {x: b1.x, y: b1.y + b1.height}); // 左下
|
||||
var b1_rb = isPointInBounding(b2, {x: b1.x + b1.width, y: b1.y + b1.height}); //右下
|
||||
var b1_lt = isPointInBound(b2, b1); // 左上
|
||||
var b1_rt = isPointInBound(b2, {x: b1.x + b1.width, y: b1.y}); // 右上
|
||||
var b1_lb = isPointInBound(b2, {x: b1.x, y: b1.y + b1.height}); // 左下
|
||||
var b1_rb = isPointInBound(b2, {x: b1.x + b1.width, y: b1.y + b1.height}); //右下
|
||||
|
||||
// b2 包含 b1
|
||||
if(b1_lt && b1_rt && b1_lb && b1_rb) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
var b2_lt = isPointInBounding(b1, b2); // 左上
|
||||
var b2_rt = isPointInBounding(b1, {x: b2.x + b2.width, y: b2.y}); // 右上
|
||||
var b2_lb = isPointInBounding(b1, {x: b2.x, y: b2.y + b2.height}); // 左下
|
||||
var b2_rb = isPointInBounding(b1, {x: b2.x + b2.width, y: b2.y + b2.height}); //右下
|
||||
var b2_lt = isPointInBound(b1, b2); // 左上
|
||||
var b2_rt = isPointInBound(b1, {x: b2.x + b2.width, y: b2.y}); // 右上
|
||||
var b2_lb = isPointInBound(b1, {x: b2.x, y: b2.y + b2.height}); // 左下
|
||||
var b2_rb = isPointInBound(b1, {x: b2.x + b2.width, y: b2.y + b2.height}); //右下
|
||||
|
||||
// b1 包含 b2
|
||||
if(b2_lt && b2_rt && b2_lb && b2_rb) {
|
||||
@@ -54,8 +45,8 @@ define(
|
||||
if(false == (b1_lt || b1_rt || b1_lb || b1_rb || b2_lt || b2_rt || b2_lb || b2_rb)) {
|
||||
// 判断十字架
|
||||
if(
|
||||
(b1.x >= b2.x && b1.x <= b2.x + b2.width)
|
||||
|| (b1.y >= b2.y && b1.y <= b2.y + b2.height)
|
||||
(b1.x > b2.x && b1.x < b2.x + b2.width)
|
||||
|| (b1.y > b2.y && b1.y < b2.y + b2.height)
|
||||
) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
28
src/graphics/isBoundingBoxSegmentCross.js
Normal file
28
src/graphics/isBoundingBoxSegmentCross.js
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* @file isBoundingBoxSegmentCross.js
|
||||
* @author mengke01
|
||||
* @date
|
||||
* @description
|
||||
* boundingbox和线段的关系
|
||||
*/
|
||||
|
||||
|
||||
define(
|
||||
function(require) {
|
||||
var isPointInBound = require('./util').isPointInBound;
|
||||
|
||||
/**
|
||||
* boundingbox和线段的关系
|
||||
*
|
||||
* @param {Object} bound bounding 1
|
||||
* @param {Object} s0 线段点1
|
||||
* @param {Object} s1 线段点2
|
||||
* @return {number} 包含关系
|
||||
*/
|
||||
function isBoundingBoxSegmentCross(bound, s0 s1) {
|
||||
|
||||
}
|
||||
|
||||
return isBoundingBoxSegmentCross;
|
||||
}
|
||||
);
|
||||
@@ -9,17 +9,144 @@
|
||||
define(
|
||||
function(require) {
|
||||
|
||||
var isBoundingBoxCross = require('./isBoundingBoxCross');
|
||||
var matrix = require('./matrix');
|
||||
var multi = matrix.multi;
|
||||
var minus = matrix.minus;
|
||||
var plus = matrix.plus;
|
||||
|
||||
/**
|
||||
* 判断点是否在bounding box内部
|
||||
*
|
||||
* @return {boolean} 是否
|
||||
*/
|
||||
function isPointInBound(bound, p) {
|
||||
return p.x <= bound.x + bound.width
|
||||
&& p.x >= bound.x
|
||||
&& p.y <= bound.y + bound.height
|
||||
&& p.y >= bound.y
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤相交重叠线段上的点
|
||||
*/
|
||||
function filter(s0, s1, t0, t1, axis) {
|
||||
var sorted = [s0, s1, t0, t1].sort(function(a, b) {
|
||||
return a[axis] < b[axis] ? -1 : 1;
|
||||
});
|
||||
|
||||
var points = [];
|
||||
|
||||
if(sorted[0][axis] == sorted[1][axis]) {
|
||||
points.push(sorted[0]);
|
||||
points.push(sorted[2]);
|
||||
}
|
||||
else if(sorted[2][axis] == sorted[3][axis]) {
|
||||
points.push(sorted[1]);
|
||||
points.push(sorted[3]);
|
||||
}
|
||||
else {
|
||||
points.push(sorted[1]);
|
||||
if(sorted[1][axis] != sorted[2][axis]) {
|
||||
points.push(sorted[2]);
|
||||
}
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
/**
|
||||
* 线段是否相交
|
||||
*
|
||||
* @param {Object} s1 点1
|
||||
* @param {Object} s2 点2
|
||||
* @param {Object} t1 点1
|
||||
* @param {Object} s0 点1
|
||||
* @param {Object} s1 点2
|
||||
* @param {Object} t0 点1
|
||||
* @param {Object} t1 点2
|
||||
* @return {boolean|Object} 是否相交
|
||||
*/
|
||||
function isSegmentCross(s1, s2, t1, t2) {
|
||||
function isSegmentCross(s0, s1, t0, t1) {
|
||||
var p, x, y;
|
||||
|
||||
if (s1.x < s0.x ) {
|
||||
p = s1;
|
||||
s1 = s0;
|
||||
s0 = p;
|
||||
}
|
||||
|
||||
if (t1.x < t0.x) {
|
||||
p = t1;
|
||||
t1 = t0;
|
||||
t0 = p;
|
||||
}
|
||||
|
||||
|
||||
var b1 = {
|
||||
x: Math.min(s0.x, s1.x),
|
||||
y: Math.min(s0.y, s1.y),
|
||||
width: Math.abs(s0.x - s1.x),
|
||||
height: Math.abs(s0.y - s1.y)
|
||||
};
|
||||
var b2 = {
|
||||
x: Math.min(t0.x, t1.x),
|
||||
y: Math.min(t0.y, t1.y),
|
||||
width: Math.abs(t0.x - t1.x),
|
||||
height: Math.abs(t0.y - t1.y)
|
||||
};
|
||||
|
||||
if (isBoundingBoxCross(b1, b2)) {
|
||||
// 参数方程 Ax + By + C = 0
|
||||
var seg1 = [s1.y - s0.y, -(s1.x - s0.x), s0.y * (s1.x - s0.x) - s0.x *(s1.y - s0.y)];
|
||||
var seg2 = [t1.y - t0.y, -(t1.x - t0.x), t0.y * (t1.x - t0.x) - t0.x *(t1.y - t0.y)];
|
||||
// x轴重叠
|
||||
if (seg1[1] == seg2[1] && seg1[1] == 0) {
|
||||
if (s1.x == t1.x) {
|
||||
return filter(s0, s1, t0, t1, 'y');
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// y轴重叠
|
||||
else if(seg1[0] == seg2[0] && seg1[0] == 0) {
|
||||
if (s1.y == t1.y) {
|
||||
return filter(s0, s1, t0, t1, 'x');
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// 平行
|
||||
else if (seg1[0] * seg2[1] == seg1[1] * seg2[0]) {
|
||||
// 重叠
|
||||
if (seg1[1] * seg2[2] == seg1[2] * seg2[1]) {
|
||||
return filter(s0, s1, t0, t1, 'x');
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
var tmp = minus(multi(seg1, seg2[0]), multi(seg2, seg1[0]));
|
||||
y = - tmp[2] / tmp[1];
|
||||
|
||||
if(seg1[0] != 0) {
|
||||
x = - (seg1[2] + seg1[1] * y) / seg1[0];
|
||||
}
|
||||
else {
|
||||
x = - (seg2[2] + seg2[1] * y) / seg2[0];
|
||||
}
|
||||
|
||||
p = {
|
||||
x: x,
|
||||
y: y
|
||||
};
|
||||
|
||||
if(isPointInBound(b1, p) && isPointInBound(b2, p)) {
|
||||
return [p];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return isSegmentCross;
|
||||
|
||||
59
src/graphics/matrix.js
Normal file
59
src/graphics/matrix.js
Normal file
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* @file matrix.js
|
||||
* @author mengke01
|
||||
* @date
|
||||
* @description
|
||||
* 一维矩阵操作
|
||||
*/
|
||||
|
||||
|
||||
define(
|
||||
function(require) {
|
||||
|
||||
|
||||
/**
|
||||
* 矩阵乘系数
|
||||
*
|
||||
* @param {Array.<number>} matrix 一维矩阵
|
||||
* @param {number} a 乘数算子
|
||||
* @return {Array.<number>} 数组
|
||||
*/
|
||||
function multi(matrix, a) {
|
||||
return matrix.map(function(item) {
|
||||
return item * a;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 矩阵减
|
||||
*
|
||||
* @param {Array.<number>} matrix1 一维矩阵
|
||||
* @param {Array.<number>} matrix2 一维矩阵
|
||||
* @return {Array.<number>} 数组
|
||||
*/
|
||||
function minus(matrix1, matrix2) {
|
||||
return matrix1.map(function(item, index) {
|
||||
return item - matrix2[index];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 矩阵加
|
||||
*
|
||||
* @param {Array.<number>} matrix1 一维矩阵
|
||||
* @param {Array.<number>} matrix2 一维矩阵
|
||||
* @return {Array.<number>} 数组
|
||||
*/
|
||||
function plus(matrix1, matrix2) {
|
||||
return matrix1.map(function(item, index) {
|
||||
return item + matrix2[index];
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
multi: multi,
|
||||
minus: minus,
|
||||
plus: plus
|
||||
};
|
||||
}
|
||||
);
|
||||
43
src/graphics/util.js
Normal file
43
src/graphics/util.js
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* @file matrix.js
|
||||
* @author mengke01
|
||||
* @date
|
||||
* @description
|
||||
* 相关工具箱
|
||||
*/
|
||||
|
||||
|
||||
define(
|
||||
function(require) {
|
||||
|
||||
/**
|
||||
* 将点进行误差舍入
|
||||
*
|
||||
* @return {Object} 点
|
||||
*/
|
||||
function ceil(p) {
|
||||
p.x = Math.ceil(p.x * 100000) / 100000;
|
||||
p.y = Math.ceil(p.y * 100000) / 100000
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断点是否在bounding box内部
|
||||
* @param {Object} bound bounding box对象
|
||||
* @param {Object} p 点对象
|
||||
* @return {boolean} 是否
|
||||
*/
|
||||
function isPointInBound(bound, p, fixed) {
|
||||
p = fixed ? ceil(p) : p;
|
||||
return p.x <= bound.x + bound.width
|
||||
&& p.x >= bound.x
|
||||
&& p.y <= bound.y + bound.height
|
||||
&& p.y >= bound.y
|
||||
}
|
||||
|
||||
return {
|
||||
ceil: ceil,
|
||||
isPointInBound: isPointInBound
|
||||
};
|
||||
}
|
||||
);
|
||||
Reference in New Issue
Block a user