Skip to content

Commit

Permalink
fix: 布尔运算曲线切割用拐点
Browse files Browse the repository at this point in the history
  • Loading branch information
army8735 committed Jan 17, 2025
1 parent 39ca6e9 commit 838cb88
Show file tree
Hide file tree
Showing 4 changed files with 226 additions and 49 deletions.
69 changes: 56 additions & 13 deletions src/math/bezier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -765,21 +765,66 @@ export function splitBezierT(points: { x: number, y: number }[], n: number, maxI
return res;
}

// 获取曲线单调性t值,有结果才返回,比如水平垂直线特例没有结果,求导看dt=0的t值
// 获取曲线1阶单调性t值,有结果才返回,比如水平垂直线特例没有结果,求导看dt=0的t值
function getBezierMonotonicityT(points: { x: number, y: number }[], isX = true, eps = 1e-9) {
if (points.length < 2 || points.length > 4) {
throw new Error('Unsupported order');
}
const p0 = isX ? points[0].x : points[0].y;
const p1 = isX ? points[1].x : points[1].y;
const p2 = isX ? points[2].x : points[2].y;
if (points.length === 4) {
const p3 = isX ? points[3].x : points[3].y;
// const t = equation
// .getRoots([
// isX ? 3 * (points[1].x - points[0].x) : 3 * (points[1].y - points[0].y),
// isX
// ? 6 * (points[2].x + points[0].x - 2 * points[1].x)
// : 6 * (points[2].y + points[0].y - 2 * points[1].y),
// isX
// ? 3 * (points[3].x + 3 * points[1].x - points[0].x - 3 * points[2].x)
// : 3 * (points[3].y + 3 * points[1].y - points[0].y - 3 * points[2].y),
// ])
// .filter((i) => i > eps&& i < 1 - eps);
const t = equation.getRoots([
3 * p1 - 3 * p0,
2 * (3 * p0 - 6 * p1 + 3 * p2),
3 * (-p0 + 3 * p1 - 3 * p2 + p3),
]).filter((i) => i > eps&& i < 1 - eps);
if (t.length) {
return t.sort(function (a, b) {
return a - b;
});
}
}
else if (points.length === 3) {
// const t = isX
// ? (points[0].x - points[1].x) /
// (points[0].x - 2 * points[1].x + points[2].x)
// : (points[0].y - points[1].y) /
// (points[0].y - 2 * points[1].y + points[2].y);
const t = equation.getRoots([
2 * (p1 - p0),
2 * (p0 - 2 * p1 + p2),
]).filter((i) => i > eps&& i < 1 - eps);
return t;
}
}

// 同上,获取2阶导单调性t值
function getBezierMonotonicityT2(points: { x: number, y: number }[], isX = true, eps = 1e-9) {
if (points.length < 2 || points.length > 4) {
throw new Error('Unsupported order');
}
const p0 = isX ? points[0].x : points[0].y;
const p1 = isX ? points[1].x : points[1].y;
const p2 = isX ? points[2].x : points[2].y;
if (points.length === 4) {
const p3 = isX ? points[3].x : points[3].y;
const t = equation
.getRoots([
isX ? 3 * (points[1].x - points[0].x) : 3 * (points[1].y - points[0].y),
isX
? 6 * (points[2].x + points[0].x - 2 * points[1].x)
: 6 * (points[2].y + points[0].y - 2 * points[1].y),
isX
? 3 * (points[3].x + 3 * points[1].x - points[0].x - 3 * points[2].x)
: 3 * (points[3].y + 3 * points[1].y - points[0].y - 3 * points[2].y),
2 * (3 * p0 - 6 * p1 + 3 * p2),
6 * (-p0 + 3 * p1 - 3 * p2 + p3),
])
.filter((i) => i > eps&& i < 1 - eps);
if (t.length) {
Expand All @@ -789,14 +834,11 @@ function getBezierMonotonicityT(points: { x: number, y: number }[], isX = true,
}
}
else if (points.length === 3) {
const t = isX
? (points[0].x - points[1].x) /
(points[0].x - 2 * points[1].x + points[2].x)
: (points[0].y - points[1].y) /
(points[0].y - 2 * points[1].y + points[2].y);
const t = 2 * (p0 - 2 * p1 + p2);
if (t > eps && t < 1 - eps) {
return [t];
}
return [];
}
}

Expand Down Expand Up @@ -1033,6 +1075,7 @@ export default {
bezierTangent,
splitBezierT,
getBezierMonotonicityT,
getBezierMonotonicityT2,
bezierDerivative,
bezierDerivative2,
bezierValue,
Expand Down
23 changes: 19 additions & 4 deletions src/math/bo/Polygon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,14 @@ class Polygon {
continue;
}
const cPoint = new Point(curr[0], curr[1]);
const t = bezier.getBezierMonotonicityT([startPoint, cPoint, endPoint], true);
if (t) {
const t = bezier.getBezierMonotonicityT2([startPoint, cPoint, endPoint], true) || [];
const t2 = bezier.getBezierMonotonicityT2([startPoint, cPoint, endPoint], false);
t2?.forEach(i => {
if (!t.includes(i)) {
t.push(i);
}
});
if (t.length) {
const points: [number, number][] = [
[startPoint.x, startPoint.y],
[curr[0], curr[1]],
Expand Down Expand Up @@ -143,11 +149,20 @@ class Polygon {
}
const cPoint1 = new Point(curr[0], curr[1]),
cPoint2 = new Point(curr[2], curr[3]);
const t = bezier.getBezierMonotonicityT(
const t = bezier.getBezierMonotonicityT2(
[startPoint, cPoint1, cPoint2, endPoint],
true,
) || [];
const t2 = bezier.getBezierMonotonicityT2(
[startPoint, cPoint1, cPoint2, endPoint],
false,
);
if (t) {
t2?.forEach(i => {
if (!t.includes(i)) {
t.push(i);
}
});
if (t.length) {
const points: Array<[number, number]> = [
[startPoint.x, startPoint.y],
[curr[0], curr[1]],
Expand Down
5 changes: 5 additions & 0 deletions src/math/bo/intersect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export function getIntersectionBezier2Line(
by2,
EPS,
EPS2,
true,
);
if (res.length) {
return filterIsec(res);
Expand Down Expand Up @@ -96,6 +97,7 @@ export function getIntersectionBezier2Bezier2(
by3,
EPS,
EPS2,
true,
);
if (res.length) {
return filterIsec(res);
Expand Down Expand Up @@ -135,6 +137,7 @@ export function getIntersectionBezier2Bezier3(
by4,
EPS,
EPS2,
true,
);
if (res.length) {
return filterIsec(res);
Expand Down Expand Up @@ -170,6 +173,7 @@ export function getIntersectionBezier3Line(
by2,
EPS,
EPS2,
true,
);
if (res.length) {
return filterIsec(res);
Expand Down Expand Up @@ -213,6 +217,7 @@ export function getIntersectionBezier3Bezier3(
by4,
EPS,
EPS2,
true,
);
if (res.length) {
return filterIsec(res);
Expand Down
Loading

0 comments on commit 838cb88

Please sign in to comment.