fonteditor/demo/js/fitCurve.js
2015-04-05 23:07:44 +08:00

171 lines
5.3 KiB
JavaScript

/**
* @file bezier曲线拟合
* @author mengke01(kekee000@gmail.com)
*/
define(
function(require) {
var fitCurve = require('graphics/image/contour/fitCurve');
var fitBezier = require('graphics/image/contour/fitBezier');
var lang = require('common/lang');
/**
* 计算bezier曲线B0参数
*
* @param {number} u t值
* @return {number}
*/
function B0(u) {
var tmp = 1.0 - u;
return (tmp * tmp * tmp);
}
/**
* 计算bezier曲线B1参数
*
* @param {number} u t值
* @return {number}
*/
function B1(u) {
var tmp = 1.0 - u;
return (3 * u * (tmp * tmp));
}
/**
* 计算bezier曲线B2参数
*
* @param {number} u t值
* @return {number}
*/
function B2(u) {
var tmp = 1.0 - u;
return (3 * u * u * tmp);
}
/**
* 计算bezier曲线B3参数
*
* @param {number} u t值
* @return {number}
*/
function B3(u) {
return (u * u * u);
}
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":50},{"x":264,"y":354},{"x":451,"y":332},{"x":600,"y":60}];
$(points).each(function(index, item) {
$('[data-index="'+index+'"]').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);
ctx.beginPath();
ctx.strokeStyle='gray';
ctx.moveTo(points[0].x, points[0].y);
ctx.bezierCurveTo(points[1].x,points[1].y,points[2].x,points[2].y,points[3].x,points[3].y);
ctx.stroke();
var curvePoints = [];
var count = 40;
var tSegment = 1 / count;
for (var i = 0; i <= count; i++) {
var t = tSegment * i;
curvePoints.push({
x: points[0].x * B0(t) + points[1].x * B1(t) + points[2].x * B2(t) + points[3].x * B3(t),
y: points[0].y * B0(t) + points[1].y * B1(t) + points[2].y * B2(t) + points[3].y * B3(t)
});
}
ctx.fillStyle='green';
for (var i = 0; i < count; i++) {
ctx.fillRect(curvePoints[i].x, curvePoints[i].y, 2, 2);
}
var result = fitCurve(lang.clone(curvePoints), 36);
result.unshift(points[0]);
console.log(result.length);
ctx.beginPath();
ctx.strokeStyle='blue';
//ctx.translate(0, 5);
ctx.moveTo(result[0].x, result[0].y);
for (var i = 1; i < result.length - 1; i+=3) {
ctx.bezierCurveTo(result[i].x, result[i].y, result[i + 1].x, result[i + 1].y, result[i + 2].x, result[i + 2].y);
ctx.moveTo(result[i + 2].x, result[i + 2].y);
}
ctx.stroke();
var bezierResult = fitBezier(lang.clone(curvePoints));
bezierResult.unshift(curvePoints[0]);
ctx.beginPath();
ctx.strokeStyle='yellow';
//ctx.translate(0, 5);
ctx.moveTo(bezierResult[0].x, bezierResult[0].y);
var last = bezierResult.length - 1;
console.log(bezierResult.length);
for (var i = 1; i < last; i+=2) {
ctx.quadraticCurveTo(bezierResult[i].x, bezierResult[i].y, bezierResult[i + 1].x, bezierResult[i + 1].y);
ctx.moveTo(bezierResult[i + 1].x, bezierResult[i + 1].y);
}
ctx.stroke();
//ctx.translate(0, -10);
}
draw();
}
};
entry.init();
return entry;
}
);