获取二次贝塞尔曲线边缘点坐标
https://stackoverflow.com/questions/999549/finding-min-max-of-quadratic-bezier-with-coregraphics
function P(x,y){
this.x = x;
this.y = y;
}
function pointOnCurve(P1,P2,P3,t){
if(t<=0 || 1<=t || isNaN(t))return false;
let c1 = new P(P1.x+(P2.x-P1.x)*t,P1.y+(P2.y-P1.y)*t);
let c2 = new P(P2.x+(P3.x-P2.x)*t,P2.y+(P3.y-P2.y)*t);
return new P(c1.x+(c2.x-c1.x)*t,c1.y+(c2.y-c1.y)*t);
}
function getQCurveBounds(ax, ay, bx, by, cx, cy){
let P1 = new P(ax,ay);
let P2 = new P(bx,by);
let P3 = new P(cx,cy);
let tx = (P1.x - P2.x) / (P1.x - 2*P2.x + P3.x);
let ty = (P1.y - P2.y) / (P1.y - 2*P2.y + P3.y);
let Ex = pointOnCurve(P1,P2,P3,tx);
let xMin = Ex?Math.min(P1.x,P3.x,Ex.x):Math.min(P1.x,P3.x);
let xMax = Ex?Math.max(P1.x,P3.x,Ex.x):Math.max(P1.x,P3.x);
let Ey = pointOnCurve(P1,P2,P3,ty);
let yMin = Ey?Math.min(P1.y,P3.y,Ey.y):Math.min(P1.y,P3.y);
let yMax = Ey?Math.max(P1.y,P3.y,Ey.y):Math.max(P1.y,P3.y);
return {x:xMin, y:yMin, width:xMax-xMin, height:yMax-yMin};
}
获取三次贝塞尔曲线边缘点坐标
function getCurveBounds(ax, ay, bx, by, cx, cy, dx, dy) {
var px, py, qx, qy, rx, ry, sx, sy, tx, ty,
tobx, toby, tocx, tocy, todx, tody, toqx, toqy,
torx, tory, totx, toty;
var x, y, minx, miny, maxx, maxy;
minx = miny = Number.POSITIVE_INFINITY;
maxx = maxy = Number.NEGATIVE_INFINITY;
tobx = bx - ax; toby = by - ay; // directions
tocx = cx - bx; tocy = cy - by;
todx = dx - cx; tody = dy - cy;
var step = 1/40; // precision
for(var d=0; d<1.001; d+=step) {
px = ax +d*tobx; py = ay +d*toby;
qx = bx +d*tocx; qy = by +d*tocy;
rx = cx +d*todx; ry = cy +d*tody;
toqx = qx - px; toqy = qy - py;
torx = rx - qx; tory = ry - qy;
sx = px +d*toqx; sy = py +d*toqy;
tx = qx +d*torx; ty = qy +d*tory;
totx = tx - sx; toty = ty - sy;
x = sx + d*totx; y = sy + d*toty;
minx = Math.min(minx, x); miny = Math.min(miny, y);
maxx = Math.max(maxx, x); maxy = Math.max(maxy, y);
}
return {x:minx, y:miny, width:maxx-minx, height:maxy-miny};
}
求赛贝尔曲线坐标
https://www.jianshu.com/p/27d3071a9b17
/**
* @param poss 贝塞尔曲线控制点坐标
* @param precision 精度,需要计算的该条贝塞尔曲线上的点的数目
* @return 该条贝塞尔曲线上的点(二维坐标)
const pos = bezier([
[0, 160],
[100, 0],
[180, 160]
], 12);
*/
function bezier(poss, precision) {
//贝塞尔曲线控制点数(阶数), 不小于 2
const number = poss.length;
if (number < 2) {
return null;
}
//维度,坐标轴数(二维坐标,三维坐标..., 至少为二维坐标系)
const dimersion = poss[0].length;
if (dimersion < 2) {
return null;
}
let i, j, k, t, temp;
//计算杨辉三角
const mi = [];
mi[0] = mi[1] = 1;
for (i = 3; i <= number; i++) {
t = [];
for (j = 0; j < i - 1; j++) {
t[j] = mi[j];
}
mi[0] = mi[i - 1] = 1;
for (j = 0; j < i - 2; j++) {
mi[j + 1] = t[j] + t[j + 1];
}
}
//计算坐标点
const result = [];
for (i = 0; i < precision; i++) {
result[i] = [];
t = i / precision;
for (j = 0; j < dimersion; j++) {
temp = 0;
for (k = 0; k < number; k++) {
temp += Math.pow(1 - t, number - k - 1) * poss[k][j] * Math.pow(t, k) * mi[k];
}
result[i][j] = temp;
}
}
result.push(poss[number - 1])
return result;
}