kopia lustrzana https://github.com/Tldraw/Tldraw
136 wiersze
3.1 KiB
TypeScript
136 wiersze
3.1 KiB
TypeScript
import { Vec2d, VecLike } from './Vec2d'
|
|
import { toDomPrecision } from './utils'
|
|
|
|
function precise(A: VecLike) {
|
|
return `${toDomPrecision(A.x)},${toDomPrecision(A.y)} `
|
|
}
|
|
|
|
function rng(seed = '') {
|
|
let x = 0
|
|
let y = 0
|
|
let z = 0
|
|
let w = 0
|
|
|
|
function next() {
|
|
const t = x ^ (x << 11)
|
|
x = y
|
|
y = z
|
|
z = w
|
|
w ^= ((w >>> 19) ^ t ^ (t >>> 8)) >>> 0
|
|
return (w / 0x100000000) * 2
|
|
}
|
|
|
|
for (let k = 0; k < seed.length + 64; k++) {
|
|
x ^= seed.charCodeAt(k) | 0
|
|
next()
|
|
}
|
|
|
|
return next
|
|
}
|
|
|
|
/** @public */
|
|
export function getRoundedInkyPolygonPath(points: VecLike[]) {
|
|
let polylineA = `M`
|
|
|
|
const len = points.length
|
|
|
|
let p0: VecLike
|
|
let p1: VecLike
|
|
let p2: VecLike
|
|
|
|
for (let i = 0, n = len; i < n; i += 3) {
|
|
p0 = points[i]
|
|
p1 = points[i + 1]
|
|
p2 = points[i + 2]
|
|
|
|
polylineA += `${precise(p0)}L${precise(p1)}Q${precise(p2)}`
|
|
}
|
|
|
|
polylineA += `${precise(points[0])}`
|
|
|
|
return polylineA
|
|
}
|
|
|
|
/** @public */
|
|
export function getRoundedPolygonPoints(
|
|
id: string,
|
|
outline: VecLike[],
|
|
offset: number,
|
|
roundness: number,
|
|
passes: number
|
|
) {
|
|
const results: VecLike[] = []
|
|
|
|
const random = rng(id)
|
|
let p0 = outline[0]
|
|
let p1: VecLike
|
|
|
|
const len = outline.length
|
|
|
|
for (let i = 0, n = len * passes; i < n; i++) {
|
|
p1 = Vec2d.AddXY(outline[(i + 1) % len], random() * offset, random() * offset)
|
|
|
|
const delta = Vec2d.Sub(p1, p0)
|
|
const distance = Vec2d.Len(delta)
|
|
const vector = Vec2d.Div(delta, distance).mul(Math.min(distance / 4, roundness))
|
|
results.push(Vec2d.Add(p0, vector), Vec2d.Add(p1, vector.neg()), p1)
|
|
|
|
p0 = p1
|
|
}
|
|
|
|
return results
|
|
}
|
|
|
|
/** @public */
|
|
export function getDrawLinePathData(id: string, outline: VecLike[], strokeWidth: number) {
|
|
let innerPathData = `M${precise(outline[0])}L`
|
|
let outerPathData1 = `M${precise(outline[0])}L`
|
|
let outerPathData2 = `M${precise(outline[0])}L`
|
|
|
|
const offset = strokeWidth / 3
|
|
const roundness = strokeWidth * 2
|
|
|
|
const random = rng(id)
|
|
let p0 = outline[0]
|
|
let p1: VecLike
|
|
|
|
let s0 = outline[0]
|
|
let s1: VecLike
|
|
|
|
const len = outline.length
|
|
|
|
for (let i = 0, n = len - 1; i < n; i++) {
|
|
p1 = Vec2d.AddXY(outline[i + 1], random() * offset, random() * offset)
|
|
s1 = Vec2d.AddXY(outline[i + 1], random(), random() * offset)
|
|
|
|
const delta = Vec2d.Sub(p1, p0)
|
|
const distance = Vec2d.Len(delta)
|
|
const vector = Vec2d.Div(delta, distance).mul(Math.min(distance / 4, roundness))
|
|
|
|
const q0 = Vec2d.Add(p0, vector)
|
|
const q1 = Vec2d.Add(p1, vector.neg())
|
|
|
|
const sDelta = Vec2d.Sub(s1, s0)
|
|
const sDistance = Vec2d.Len(sDelta)
|
|
const sVector = Vec2d.Div(sDelta, sDistance).mul(Math.min(sDistance / 4, roundness))
|
|
|
|
const sq0 = Vec2d.Add(s0, sVector)
|
|
const sq1 = Vec2d.Add(s1, sVector.neg())
|
|
|
|
if (i === n - 1) {
|
|
innerPathData += `${precise(q0)} L ${precise(p1)}`
|
|
outerPathData1 += `${precise(q0)} L ${precise(p1)}`
|
|
outerPathData2 += `${precise(sq0)} L ${precise(s1)}`
|
|
} else {
|
|
innerPathData += `${precise(q0)}L ${precise(q1)}Q ${precise(p1)}`
|
|
outerPathData1 += `${precise(q0)}L ${precise(q1)}Q ${precise(p1)}`
|
|
outerPathData2 += `${precise(sq0)}L ${precise(sq1)}Q ${precise(s1)}`
|
|
|
|
p0 = p1
|
|
s0 = s1
|
|
}
|
|
}
|
|
|
|
return [innerPathData, outerPathData1 + outerPathData2]
|
|
}
|