mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-27 02:42:25 +08:00
refactor(editor): add gfx entry in bs global package (#10612)
This commit is contained in:
136
blocksuite/framework/global/src/gfx/polyline.ts
Normal file
136
blocksuite/framework/global/src/gfx/polyline.ts
Normal file
@@ -0,0 +1,136 @@
|
||||
import { type IVec, Vec } from './model/index.js';
|
||||
|
||||
export class Polyline {
|
||||
static len(points: IVec[]) {
|
||||
const n = points.length;
|
||||
|
||||
if (n < 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let i = 0;
|
||||
let len = 0;
|
||||
let curr: IVec;
|
||||
let prev = points[0];
|
||||
|
||||
while (++i < n) {
|
||||
curr = points[i];
|
||||
len += Vec.dist(prev, curr);
|
||||
prev = curr;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static lenAtPoint(points: IVec[], point: IVec) {
|
||||
const n = points.length;
|
||||
let len = n;
|
||||
|
||||
for (let i = 0; i < n - 1; i++) {
|
||||
const a = points[i];
|
||||
const b = points[i + 1];
|
||||
|
||||
// start
|
||||
if (a[0] === point[0] && a[1] === point[1]) {
|
||||
return len;
|
||||
}
|
||||
|
||||
const aa = Vec.angle(a, point);
|
||||
const ba = Vec.angle(b, point);
|
||||
|
||||
if ((aa + ba) % Math.PI === 0) {
|
||||
len += Vec.dist(a, point);
|
||||
return len;
|
||||
}
|
||||
|
||||
len += Vec.dist(a, b);
|
||||
|
||||
// end
|
||||
if (b[0] === point[0] && b[1] === point[1]) {
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static nearestPoint(points: IVec[], point: IVec): IVec {
|
||||
const n = points.length;
|
||||
const r: IVec = [0, 0];
|
||||
let len = Infinity;
|
||||
|
||||
for (let i = 0; i < n - 1; i++) {
|
||||
const a = points[i];
|
||||
const b = points[i + 1];
|
||||
const p = Vec.nearestPointOnLineSegment(a, b, point, true);
|
||||
const d = Vec.dist(p, point);
|
||||
if (d < len) {
|
||||
len = d;
|
||||
r[0] = p[0];
|
||||
r[1] = p[1];
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static pointAt(points: IVec[], ratio: number) {
|
||||
const n = points.length;
|
||||
|
||||
if (n === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (n === 1) {
|
||||
return points[0];
|
||||
}
|
||||
|
||||
if (ratio <= 0) {
|
||||
return points[0];
|
||||
}
|
||||
|
||||
if (ratio >= 1) {
|
||||
return points[n - 1];
|
||||
}
|
||||
|
||||
const total = Polyline.len(points);
|
||||
const len = total * ratio;
|
||||
return Polyline.pointAtLen(points, len);
|
||||
}
|
||||
|
||||
static pointAtLen(points: IVec[], len: number): IVec | null {
|
||||
const n = points.length;
|
||||
|
||||
if (n === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (n === 1) {
|
||||
return points[0];
|
||||
}
|
||||
|
||||
let fromStart = true;
|
||||
if (len < 0) {
|
||||
fromStart = false;
|
||||
len = -len;
|
||||
}
|
||||
|
||||
let tmp = 0;
|
||||
for (let j = 0, k = n - 1; j < k; j++) {
|
||||
const i = fromStart ? j : k - 1 - j;
|
||||
const a = points[i];
|
||||
const b = points[i + 1];
|
||||
const d = Vec.dist(a, b);
|
||||
|
||||
if (len <= tmp + d) {
|
||||
const t = ((fromStart ? 1 : -1) * (len - tmp)) / d;
|
||||
return Vec.lrp(a, b, t) as IVec;
|
||||
}
|
||||
|
||||
tmp += d;
|
||||
}
|
||||
|
||||
const lastPoint = fromStart ? points[n - 1] : points[0];
|
||||
return lastPoint;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user