Skip to content

Instantly share code, notes, and snippets.

@juliendargelos
Created January 23, 2020 09:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save juliendargelos/e732dba799ff3c59d35483f7f8eac360 to your computer and use it in GitHub Desktop.
Save juliendargelos/e732dba799ff3c59d35483f7f8eac360 to your computer and use it in GitHub Desktop.
Create 2D arc-edged path from a list of points and radii (wip)
import { Vector2, Path } from 'three'
export function arcEdgedPath(
path: Path,
points: Vector2[],
radius: number,
close?: boolean
): void
export function arcEdgedPath(
path: Path,
points: Vector2[],
radii: number[],
close?: boolean
): void
export function arcEdgedPath(
path: Path,
points: Vector2[],
radii: number | number[],
close: boolean = false
): void {
const pointsLength: number = points.length
if (pointsLength < 3) {
throw new Error('Cannot create arc-edged path with less than 3 points')
}
if (!Array.isArray(radii)) {
radii = [radii]
}
const radiiLength: number = radii.length
const pathLength: number = close ? pointsLength : pointsLength - 1
const u: Vector2 = new Vector2()
const v: Vector2 = new Vector2()
const s: Vector2 = new Vector2()
let radius!: number
let edge!: Vector2
let sign!: number
let edgeFactor!: number
let centerFactor!: number
let centerX!: number
let centerY!: number
let startEdgeX!: number
let startEdgeY!: number
let startAngle!: number
let endEdgeX!: number
let endEdgeY!: number
let endAngle!: number
for (var index: number = 0; index < pathLength; index++) {
radius = radii[index % radiiLength]
edge = points[(index + 1) % pointsLength]
u.subVectors(points[index % pointsLength], edge).normalize()
v.subVectors(points[(index + 2) % pointsLength], edge).normalize()
sign = s.set(v.y, -v.x).dot(u) > 0 ? 1 : -1
centerFactor = sign * radius / (u.x * v.y - v.x * u.y)
edgeFactor = centerFactor * (u.dot(v) + 1)
centerX = edge.x + centerFactor * (u.x + v.x)
centerY = edge.y + centerFactor * (u.y + v.y)
startEdgeX = edge.x + edgeFactor * u.x
startEdgeY = edge.y + edgeFactor * u.y
startAngle = Math.atan2(startEdgeY - centerY, startEdgeX - centerX)
endEdgeX = edge.x + edgeFactor * v.x
endEdgeY = edge.y + edgeFactor * v.y
endAngle = Math.atan2(endEdgeY - centerY, endEdgeX - centerX)
if (index) path.lineTo(startEdgeX, startEdgeY)
else path.moveTo(startEdgeX, startEdgeY)
path.arc(
centerX - startEdgeX,
centerY - startEdgeY,
radius,
startAngle,
endAngle,
sign === 1
)
path.moveTo(endEdgeX, endEdgeY)
}
}
@juliendargelos
Copy link
Author

arc-edged-path

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment